add level component saving functions which use PhysicsFS (didn't commit properly...
[btb/d2x.git] / arch / ogl / ogl.c
1 /* $Id: ogl.c,v 1.36 2004-11-14 09:50:36 schaffner Exp $ */
2 /*
3  *
4  * Graphics support functions for OpenGL.
5  *
6  *
7  */
8
9 #ifdef HAVE_CONFIG_H
10 #include <conf.h>
11 #endif
12
13 //#include <stdio.h>
14 #ifdef _WIN32
15 #include <windows.h>
16 #include <stddef.h>
17 #endif
18 #include "internal.h"
19 #if defined(__APPLE__) && defined(__MACH__)
20 #include <OpenGL/gl.h>
21 #include <OpenGL/glu.h>
22 #else
23 #include <GL/gl.h>
24 #include <GL/glu.h>
25 #endif
26 #include <string.h>
27 #include <math.h>
28 #include <stdio.h>
29
30 #include "3d.h"
31 #include "piggy.h"
32 #include "../../3d/globvars.h"
33 #include "error.h"
34 #include "texmap.h"
35 #include "palette.h"
36 #include "rle.h"
37 #include "mono.h"
38 #ifdef HAVE_LIBPNG
39 #include "pngfile.h"
40 #endif
41
42 #include "segment.h"
43 #include "textures.h"
44 #include "texmerge.h"
45 #include "effects.h"
46 #include "weapon.h"
47 #include "powerup.h"
48 #include "laser.h"
49 #include "player.h"
50 #include "polyobj.h"
51 #include "gamefont.h"
52 #include "byteswap.h"
53
54 //change to 1 for lots of spew.
55 #if 0
56 #define glmprintf(a) mprintf(a)
57 #else
58 #define glmprintf(a)
59 #endif
60
61 #ifndef M_PI
62 #define M_PI 3.14159
63 #endif
64
65 #if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__) || defined(macintosh)
66 #define cosf(a) cos(a)
67 #define sinf(a) sin(a)
68 #endif
69
70 unsigned char *ogl_pal=gr_palette;
71
72 int GL_texmagfilt=GL_NEAREST;
73 int GL_texminfilt=GL_NEAREST;
74 float GL_texanisofilt = 0;
75 int GL_needmipmaps=0;
76
77 int last_width=-1,last_height=-1;
78 int GL_TEXTURE_2D_enabled=-1;
79 int GL_texclamp_enabled=-1;
80
81 extern int gr_badtexture;
82 int r_texcount = 0, r_cachedtexcount = 0;
83 int ogl_alttexmerge=1;//merge textures by just printing the seperate textures?
84 int ogl_rgba_internalformat = GL_RGBA8;
85 int ogl_rgb_internalformat = GL_RGB8;
86 int ogl_intensity4_ok=1;
87 int ogl_luminance4_alpha4_ok=1;
88 int ogl_rgba2_ok=1;
89 int ogl_readpixels_ok=1;
90 int ogl_gettexlevelparam_ok=1;
91 #ifdef GL_ARB_multitexture
92 int ogl_arb_multitexture_ok=0;
93 #endif
94 #ifdef GL_SGIS_multitexture
95 int ogl_sgis_multitexture_ok=0;
96 #endif
97 int ogl_nv_texture_env_combine4_ok = 0;
98 #ifdef GL_NV_register_combiners
99 int ogl_nv_register_combiners_ok = 0;
100 #endif
101 int ogl_ext_texture_filter_anisotropic_ok = 0;
102 #ifdef GL_EXT_paletted_texture
103 int ogl_shared_palette_ok = 0;
104 int ogl_paletted_texture_ok = 0;
105 #endif
106
107 int sphereh=0;
108 int cross_lh[2]={0,0};
109 int primary_lh[3]={0,0,0};
110 int secondary_lh[5]={0,0,0,0,0};
111 /*int lastbound=-1;
112
113 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
114         else if(a!=lastbound) {glBindTexture(GL_TEXTURE_2D, a);lastbound=a;}*/
115 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
116         else glBindTexture(GL_TEXTURE_2D, a);
117
118
119 ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE];
120 int ogl_texture_list_cur;
121
122 /* some function prototypes */
123
124 //#define OGLTEXBUFSIZE (1024*1024*4)
125 #define OGLTEXBUFSIZE (2048*2048*4)
126 extern GLubyte texbuf[OGLTEXBUFSIZE];
127 //void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int width,int height,int  twidth,int theight);
128 void ogl_filltexbuf(unsigned char *data, GLubyte *texp, int truewidth, int width, int height, int dxo, int dyo, int twidth, int theight, int type, int bm_flags, int data_format);
129 void ogl_loadbmtexture(grs_bitmap *bm);
130 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,intdyo , int *texid,float *u,float *v,char domipmap,float prio);
131 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format);
132 void ogl_freetexture(ogl_texture *gltexture);
133 void ogl_do_palfx(void);
134
135 void ogl_init_texture_stats(ogl_texture* t){
136         t->prio=0.3;//default prio
137         t->lastrend=0;
138         t->numrend=0;
139 }
140 void ogl_init_texture(ogl_texture* t, int w, int h, int flags)
141 {
142         t->handle = 0;
143         if (flags & OGL_FLAG_NOCOLOR)
144         {
145                 // use GL_INTENSITY instead of GL_RGB
146                 if (flags & OGL_FLAG_ALPHA)
147                 {
148                         if (ogl_intensity4_ok)
149                         {
150                                 t->internalformat = GL_INTENSITY4;
151                                 t->format = GL_LUMINANCE;
152                         }
153                         else if (ogl_luminance4_alpha4_ok)
154                         {
155                                 t->internalformat = GL_LUMINANCE4_ALPHA4;
156                                 t->format = GL_LUMINANCE_ALPHA;
157                         }
158                         else if (ogl_rgba2_ok)
159                         {
160                                 t->internalformat = GL_RGBA2;
161                                 t->format = GL_RGBA;
162                         }
163                         else
164                         {
165                                 t->internalformat = ogl_rgba_internalformat;
166                                 t->format = GL_RGBA;
167                         }
168                 }
169                 else
170                 {
171                         // there are certainly smaller formats we could use here, but nothing needs it ATM.
172                         t->internalformat = ogl_rgb_internalformat;
173                         t->format = GL_RGB;
174                 }
175         }
176         else
177         {
178                 if (flags & OGL_FLAG_ALPHA)
179                 {
180                         t->internalformat = ogl_rgba_internalformat;
181                         t->format = GL_RGBA;
182                 }
183                 else
184                 {
185                         t->internalformat = ogl_rgb_internalformat;
186                         t->format = GL_RGB;
187                 }
188         }
189         t->wrapstate[0] = -1;
190         t->wrapstate[1] = -1;
191         t->lw = t->w = w;
192         t->h = h;
193         t->wantmip = flags & OGL_FLAG_MIPMAP;
194         ogl_init_texture_stats(t);
195 }
196
197 void ogl_reset_texture(ogl_texture* t)
198 {
199         ogl_init_texture(t, 0, 0, 0);
200 }
201
202 void ogl_reset_texture_stats_internal(void){
203         int i;
204         for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
205                 if (ogl_texture_list[i].handle>0){
206                         ogl_init_texture_stats(&ogl_texture_list[i]);
207                 }
208 }
209 void ogl_init_texture_list_internal(void){
210         int i;
211         ogl_texture_list_cur=0;
212         for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
213                 ogl_reset_texture(&ogl_texture_list[i]);
214 }
215 void ogl_smash_texture_list_internal(void){
216         int i;
217         sphereh=0;
218         memset(cross_lh,0,sizeof(cross_lh));
219         memset(primary_lh,0,sizeof(primary_lh));
220         memset(secondary_lh,0,sizeof(secondary_lh));
221         for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
222                 if (ogl_texture_list[i].handle>0){
223                         glDeleteTextures( 1, &ogl_texture_list[i].handle );
224                         ogl_texture_list[i].handle=0;
225                 }
226                 ogl_texture_list[i].wrapstate[0] = -1;
227                 ogl_texture_list[i].wrapstate[1] = -1;
228         }
229 }
230 void ogl_vivify_texture_list_internal(void){
231 /*
232    int i;
233         ogl_texture* t;
234         for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
235                 t=&ogl_texture_list[i];
236                 if (t->w>0){//erk, realised this can't be done since we'd need the texture bm_data too. hmmm.
237                         ogl_loadbmtexture(t);
238         }
239 */
240 }
241
242 ogl_texture* ogl_get_free_texture(void){
243         int i;
244         for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
245                 if (ogl_texture_list[ogl_texture_list_cur].handle<=0 && ogl_texture_list[ogl_texture_list_cur].w==0)
246                         return &ogl_texture_list[ogl_texture_list_cur];
247                 if (++ogl_texture_list_cur>=OGL_TEXTURE_LIST_SIZE)
248                         ogl_texture_list_cur=0;
249         }
250         Error("OGL: texture list full!\n");
251 //      return NULL;
252 }
253 int ogl_texture_stats(void){
254         int used = 0, usedother = 0, usedidx = 0, usedrgb = 0, usedrgba = 0;
255         int databytes = 0, truebytes = 0, datatexel = 0, truetexel = 0, i;
256         int prio0=0,prio1=0,prio2=0,prio3=0,prioh=0;
257 //      int grabbed=0;
258         ogl_texture* t;
259         for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
260                 t=&ogl_texture_list[i];
261                 if (t->handle>0){
262                         used++;
263                         datatexel+=t->w*t->h;
264                         truetexel+=t->tw*t->th;
265                         databytes+=t->bytesu;
266                         truebytes+=t->bytes;
267                         if (t->prio<0.299)prio0++;
268                         else if (t->prio<0.399)prio1++;
269                         else if (t->prio<0.499)prio2++;
270                         else if (t->prio<0.599)prio3++;
271                         else prioh++;
272                         if (t->format == GL_RGBA)
273                                 usedrgba++;
274                         else if (t->format == GL_RGB)
275                                 usedrgb++;
276                         else if (t->format == GL_COLOR_INDEX)
277                                 usedidx++;
278                         else
279                                 usedother++;
280                 }
281 //              else if(t->w!=0)
282 //                      grabbed++;
283         }
284         if (gr_renderstats)
285         {
286                 GLint idx, r, g, b, a, dbl, depth;
287                 int res, colorsize, depthsize;
288
289                 res = SWIDTH * SHEIGHT;
290                 glGetIntegerv(GL_INDEX_BITS, &idx);
291                 glGetIntegerv(GL_RED_BITS, &r);
292                 glGetIntegerv(GL_GREEN_BITS, &g);
293                 glGetIntegerv(GL_BLUE_BITS, &b);
294                 glGetIntegerv(GL_ALPHA_BITS, &a);
295                 glGetIntegerv(GL_DOUBLEBUFFER, &dbl);
296                 dbl += 1;
297                 glGetIntegerv(GL_DEPTH_BITS, &depth);
298                 colorsize = (idx * res * dbl) / 8;
299                 depthsize = res * depth / 8;
300                 gr_printf(5, GAME_FONT->ft_h * 14 + 3 * 14, "%i(%i,%i,%i,%i) %iK(%iK wasted) (%i postcachedtex)", used, usedrgba, usedrgb, usedidx, usedother, truebytes / 1024, (truebytes - databytes) / 1024, r_texcount - r_cachedtexcount);
301                 gr_printf(5, GAME_FONT->ft_h * 15 + 3 * 15, "%ibpp(r%i,g%i,b%i,a%i)x%i=%iK depth%i=%iK", idx, r, g, b, a, dbl, colorsize / 1024, depth, depthsize / 1024);
302                 gr_printf(5, GAME_FONT->ft_h * 16 + 3 * 16, "total=%iK", (colorsize + depthsize + truebytes) / 1024);
303         }
304 //      glmprintf((0,"ogl tex stats: %i(%i,%i|%i,%i,%i,%i,%i) %i(%i)b (%i(%i)wasted)\n",used,usedrgba,usedl4a4,prio0,prio1,prio2,prio3,prioh,truebytes,truetexel,truebytes-databytes,truetexel-datatexel));
305         return truebytes;
306 }
307 int ogl_mem_target=-1;
308 void ogl_clean_texture_cache(void){
309         ogl_texture* t;
310         int i,bytes;
311         int time=120;
312         
313         if (ogl_mem_target<0){
314                 if (gr_renderstats)
315                         ogl_texture_stats();
316                 return;
317         }
318         
319         bytes=ogl_texture_stats();
320         while (bytes>ogl_mem_target){
321                 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
322                         t=&ogl_texture_list[i];
323                         if (t->handle>0){
324                                 if (t->lastrend+f1_0*time<GameTime){
325                                         ogl_freetexture(t);
326                                         bytes-=t->bytes;
327                                         if (bytes<ogl_mem_target)
328                                                 return;
329                                 }
330                         }
331                 }
332                 if (time==0)
333                         Error("not enough mem?");
334                 time=time/2;
335         }
336         
337 }
338 void ogl_bindbmtex(grs_bitmap *bm){
339         if (bm->gltexture==NULL || bm->gltexture->handle<=0)
340                 ogl_loadbmtexture(bm);
341         OGL_BINDTEXTURE(bm->gltexture->handle);
342         bm->gltexture->lastrend=GameTime;
343         bm->gltexture->numrend++;
344 ////    if (bm->gltexture->numrend==80 || bm->gltexture->numrend==4000 || bm->gltexture->numrend==80000){
345 //      if (bm->gltexture->numrend==100){
346 //              bm->gltexture->prio+=0.1;
347 ////            glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY,bm->gltexture->prio);
348 //              glPrioritizeTextures(1,&bm->gltexture->handle,&bm->gltexture->prio);
349 //      }
350 }
351 //gltexture MUST be bound first
352 void ogl_texwrap(ogl_texture *gltexture,int state)
353 {
354         if (gltexture->wrapstate[active_texture_unit] != state || gltexture->numrend < 1)
355         {
356                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state);
357                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state);
358                 gltexture->wrapstate[active_texture_unit] = state;
359         }
360 }
361
362 //crude texture precaching
363 //handles: powerups, walls, weapons, polymodels, etc.
364 //it is done with the horrid do_special_effects kludge so that sides that have to be texmerged and have animated textures will be correctly cached.
365 //similarly, with the objects(esp weapons), we could just go through and cache em all instead, but that would get ones that might not even be on the level
366 //TODO: doors
367
368 void ogl_cache_polymodel_textures(int model_num)
369 {
370         polymodel *po;
371         int i;
372
373         if (model_num < 0)
374                 return;
375         po = &Polygon_models[model_num];
376         for (i=0;i<po->n_textures;i++)  {
377 //              texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
378                 ogl_loadbmtexture(&GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]);
379         }
380 }
381 void ogl_cache_vclip_textures(vclip *vc){
382         int i;
383         for (i=0;i<vc->num_frames;i++){
384                 PIGGY_PAGE_IN(vc->frames[i]);
385                 ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]);
386         }
387 }
388
389 void ogl_cache_vclipn_textures(int i)
390 {
391         if (i >= 0 && i < VCLIP_MAXNUM)
392                 ogl_cache_vclip_textures(&Vclip[i]);
393 }
394
395 void ogl_cache_weapon_textures(int weapon_type)
396 {
397         weapon_info *w;
398
399         if (weapon_type < 0)
400                 return;
401         w = &Weapon_info[weapon_type];
402         ogl_cache_vclipn_textures(w->flash_vclip);
403         ogl_cache_vclipn_textures(w->robot_hit_vclip);
404         ogl_cache_vclipn_textures(w->wall_hit_vclip);
405         if (w->render_type==WEAPON_RENDER_VCLIP)
406                 ogl_cache_vclipn_textures(w->weapon_vclip);
407         else if (w->render_type == WEAPON_RENDER_POLYMODEL)
408         {
409                 ogl_cache_polymodel_textures(w->model_num);
410                 ogl_cache_polymodel_textures(w->model_num_inner);
411         }
412 }
413
414 void ogl_cache_level_textures(void)
415 {
416         int seg,side,i;
417         eclip *ec;
418         short tmap1,tmap2;
419         grs_bitmap *bm,*bm2;
420         struct side *sidep;
421         int max_efx=0,ef;
422         
423         ogl_reset_texture_stats_internal();//loading a new lev should reset textures
424         
425         for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
426                 ogl_cache_vclipn_textures(Effects[i].dest_vclip);
427                 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
428                         continue;
429                 if (ec->vc.num_frames>max_efx)
430                         max_efx=ec->vc.num_frames;
431         }
432         glmprintf((0,"max_efx:%i\n",max_efx));
433         for (ef=0;ef<max_efx;ef++){
434                 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
435                         if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
436                                 continue;
437 //                      if (ec->vc.num_frames>max_efx)
438 //                              max_efx=ec->vc.num_frames;
439                         ec->time_left=-1;
440                 }
441                 do_special_effects();
442
443                 for (seg=0;seg<Num_segments;seg++){
444                         for (side=0;side<MAX_SIDES_PER_SEGMENT;side++){
445                                 sidep=&Segments[seg].sides[side];
446                                 tmap1=sidep->tmap_num;
447                                 tmap2=sidep->tmap_num2;
448                                 if (tmap1<0 || tmap1>=NumTextures){
449                                         glmprintf((0,"ogl_cache_level_textures %i %i %i %i\n",seg,side,tmap1,NumTextures));
450                                         //                              tmap1=0;
451                                         continue;
452                                 }
453                                 PIGGY_PAGE_IN(Textures[tmap1]);
454                                 bm = &GameBitmaps[Textures[tmap1].index];
455                                 if (tmap2 != 0){
456                                         PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]);
457                                         bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index];
458                                         if (ogl_alttexmerge == 0 || (!OGL_SUPER_TRANSPARENT_OK && (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT)))
459                                                 bm = texmerge_get_cached_bitmap( tmap1, tmap2 );
460                                         else {
461                                                 ogl_loadbmtexture(bm2);
462                                         }
463                                         //                              glmprintf((0,"ogl_cache_level_textures seg %i side %i t1 %i t2 %x bm %p NT %i\n",seg,side,tmap1,tmap2,bm,NumTextures));
464                                 }
465                                 ogl_loadbmtexture(bm);
466                         }
467                 }
468                 glmprintf((0,"finished ef:%i\n",ef));
469         }
470         reset_special_effects();
471         init_special_effects();
472         {
473 //              int laserlev=1;
474
475                 // always have lasers, concs, flares.  Always shows player appearance, and at least concs are always available to disappear.
476                 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
477                 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
478                 ogl_cache_weapon_textures(FLARE_ID);
479                 ogl_cache_vclipn_textures(VCLIP_PLAYER_APPEARANCE);
480                 ogl_cache_vclipn_textures(VCLIP_POWERUP_DISAPPEARANCE);
481                 ogl_cache_polymodel_textures(Player_ship->model_num);
482                 ogl_cache_vclipn_textures(Player_ship->expl_vclip_num);
483
484                 for (i=0;i<Highest_object_index;i++){
485                         if(Objects[i].render_type==RT_POWERUP){
486                                 ogl_cache_vclipn_textures(Objects[i].rtype.vclip_info.vclip_num);
487                                 switch (Objects[i].id){
488 /*                                      case POW_LASER:
489                                                 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
490 //                                              if (laserlev<4)
491 //                                                      laserlev++;
492                                                 break;*/
493                                         case POW_VULCAN_WEAPON:
494                                                 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]);
495                                                 break;
496                                         case POW_SPREADFIRE_WEAPON:
497                                                 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]);
498                                                 break;
499                                         case POW_PLASMA_WEAPON:
500                                                 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]);
501                                                 break;
502                                         case POW_FUSION_WEAPON:
503                                                 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]);
504                                                 break;
505 /*                                      case POW_MISSILE_1:
506                                         case POW_MISSILE_4:
507                                                 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
508                                                 break;*/
509                                         case POW_PROXIMITY_WEAPON:
510                                                 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]);
511                                                 break;
512                                         case POW_HOMING_AMMO_1:
513                                         case POW_HOMING_AMMO_4:
514                                                 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]);
515                                                 break;
516                                         case POW_SMARTBOMB_WEAPON:
517                                                 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]);
518                                                 break;
519                                         case POW_MEGA_WEAPON:
520                                                 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]);
521                                                 break;
522                                 }
523                         }
524                         else if(Objects[i].render_type==RT_POLYOBJ){
525                                 //printf("robot %i model %i rmodel %i\n", Objects[i].id, Objects[i].rtype.pobj_info.model_num, Robot_info[Objects[i].id].model_num);
526                                 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp1_vclip_num);
527                                 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp2_vclip_num);
528                                 ogl_cache_weapon_textures(Robot_info[Objects[i].id].weapon_type);
529                                 ogl_cache_polymodel_textures(Objects[i].rtype.pobj_info.model_num);
530                         }
531                 }
532         }
533         glmprintf((0,"finished caching\n"));
534         r_cachedtexcount = r_texcount;
535 }
536
537 int r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc;
538 #define f2glf(x) (f2fl(x))
539
540 bool g3_draw_line(g3s_point *p0,g3s_point *p1)
541 {
542         int c;
543         c=grd_curcanv->cv_color;
544         OGL_DISABLE(TEXTURE_2D);
545         glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
546         glBegin(GL_LINES);
547         glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));
548         glVertex3f(f2glf(p1->p3_vec.x),f2glf(p1->p3_vec.y),-f2glf(p1->p3_vec.z));
549         glEnd();
550         return 1;
551 }
552 void ogl_drawcircle2(int nsides,int type,float xsc,float xo,float ysc,float yo){
553         int i;
554         float ang;
555         glBegin(type);
556         for (i=0; i<nsides; i++) {
557                 ang = 2.0*M_PI*i/nsides;
558                 glVertex2f(cosf(ang)*xsc+xo,sinf(ang)*ysc+yo);
559         }
560         glEnd();
561 }
562 void ogl_drawcircle(int nsides,int type){
563         int i;
564         float ang;
565         glBegin(type);
566         for (i=0; i<nsides; i++) {
567                 ang = 2.0*M_PI*i/nsides;
568                 glVertex2f(cosf(ang),sinf(ang));
569         }
570         glEnd();
571 }
572 int circle_list_init(int nsides,int type,int mode) {
573         int hand=glGenLists(1);
574         glNewList(hand, mode);
575         /* draw a unit radius circle in xy plane centered on origin */
576         ogl_drawcircle(nsides,type);
577         glEndList();
578         return hand;
579 }
580 float bright_g[4]={     32.0/256,       252.0/256,      32.0/256};
581 float dark_g[4]={       32.0/256,       148.0/256,      32.0/256};
582 float darker_g[4]={     32.0/256,       128.0/256,      32.0/256};
583 void ogl_draw_reticle(int cross,int primary,int secondary){
584         float scale=(float)Canvas_height/(float)grd_curscreen->sc_h;
585         glPushMatrix();
586 //      glTranslatef(0.5,0.5,0);
587         glTranslatef((grd_curcanv->cv_bitmap.bm_w/2+grd_curcanv->cv_bitmap.bm_x)/(float)last_width,1.0-(grd_curcanv->cv_bitmap.bm_h/2+grd_curcanv->cv_bitmap.bm_y)/(float)last_height,0);
588         glScalef(scale/320.0,scale/200.0,scale);//the positions are based upon the standard reticle at 320x200 res.
589         
590         OGL_DISABLE(TEXTURE_2D);
591
592         if (!cross_lh[cross]){
593                 cross_lh[cross]=glGenLists(1);
594                 glNewList(cross_lh[cross], GL_COMPILE_AND_EXECUTE);
595                 glBegin(GL_LINES);
596                 //cross top left
597                 glColor3fv(darker_g);
598                 glVertex2f(-4.0,4.0);
599                 if (cross)
600                         glColor3fv(bright_g);
601                 else
602                         glColor3fv(dark_g);
603                 glVertex2f(-2.0,2.0);
604
605                 //cross bottom left
606                 glColor3fv(dark_g);
607                 glVertex2f(-3.0,-2.0);
608                 if (cross)
609                         glColor3fv(bright_g);
610                 glVertex2f(-2.0,-1.0);
611
612                 //cross top right
613                 glColor3fv(darker_g);
614                 glVertex2f(4.0,4.0);
615                 if (cross)
616                         glColor3fv(bright_g);
617                 else
618                         glColor3fv(dark_g);
619                 glVertex2f(2.0,2.0);
620
621                 //cross bottom right
622                 glColor3fv(dark_g);
623                 glVertex2f(3.0,-2.0);
624                 if (cross)
625                         glColor3fv(bright_g);
626                 glVertex2f(2.0,-1.0);
627
628                 glEnd();
629                 glEndList();
630         }else
631                 glCallList(cross_lh[cross]);
632
633 //      if (Canvas_height>200)
634 //              glLineWidth(Canvas_height/(float)200);
635         if (!primary_lh[primary]){
636                 primary_lh[primary]=glGenLists(1);
637                 glNewList(primary_lh[primary], GL_COMPILE_AND_EXECUTE);
638
639                 glColor3fv(dark_g);
640                 glBegin(GL_LINES);
641                 //left primary bar
642                 glVertex2f(-14.0,-8.0);
643                 glVertex2f(-8.0,-5.0);
644                 //right primary bar
645                 glVertex2f(14.0,-8.0);
646                 glVertex2f(8.0,-5.0);
647                 glEnd();
648                 if (primary==0)
649                         glColor3fv(dark_g);
650                 else
651                         glColor3fv(bright_g);
652                 //left upper
653                 ogl_drawcircle2(6,GL_POLYGON,1.5,-7.0,1.5,-5.0);
654                 //right upper
655                 ogl_drawcircle2(6,GL_POLYGON,1.5,7.0,1.5,-5.0);
656                 if (primary!=2)
657                         glColor3fv(dark_g);
658                 else
659                         glColor3fv(bright_g);
660                 //left lower
661                 ogl_drawcircle2(4,GL_POLYGON,1.0,-14.0,1.0,-8.0);
662                 //right lower
663                 ogl_drawcircle2(4,GL_POLYGON,1.0,14.0,1.0,-8.0);
664
665                 glEndList();
666         }else
667                 glCallList(primary_lh[primary]);
668 //      if (Canvas_height>200)
669 //              glLineWidth(1);
670
671         if (!secondary_lh[secondary]){
672                 secondary_lh[secondary]=glGenLists(1);
673                 glNewList(secondary_lh[secondary], GL_COMPILE_AND_EXECUTE);
674                 if (secondary<=2){
675                         //left secondary
676                         if (secondary!=1)
677                                 glColor3fv(darker_g);
678                         else
679                                 glColor3fv(bright_g);
680                         ogl_drawcircle2(8,GL_LINE_LOOP,2.0,-10.0,2.0,-1.0);
681                         //right secondary
682                         if (secondary!=2)
683                                 glColor3fv(darker_g);
684                         else
685                                 glColor3fv(bright_g);
686                         ogl_drawcircle2(8,GL_LINE_LOOP,2.0,10.0,2.0,-1.0);
687                 }else{
688                         //bottom/middle secondary
689                         if (secondary!=4)
690                                 glColor3fv(darker_g);
691                         else
692                                 glColor3fv(bright_g);
693                         ogl_drawcircle2(8,GL_LINE_LOOP,2.0,0.0,2.0,-7.0);
694                 }
695                 glEndList();
696         }else
697                 glCallList(secondary_lh[secondary]);
698
699         glPopMatrix();
700 }
701 int g3_draw_sphere(g3s_point *pnt,fix rad){
702         int c;
703         c=grd_curcanv->cv_color;
704         OGL_DISABLE(TEXTURE_2D);
705 //      glPointSize(f2glf(rad));
706         glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
707 //      glBegin(GL_POINTS);
708 //      glVertex3f(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
709 //      glEnd();
710         glPushMatrix();
711         glTranslatef(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
712         glScalef(f2glf(rad),f2glf(rad),f2glf(rad));
713         if (!sphereh) sphereh=circle_list_init(20,GL_POLYGON,GL_COMPILE_AND_EXECUTE);
714         else glCallList(sphereh);
715         glPopMatrix();
716         return 0;
717
718 }
719 int gr_ucircle(fix xc1, fix yc1, fix r1)
720 {
721         int c;
722         c=grd_curcanv->cv_color;
723         OGL_DISABLE(TEXTURE_2D);
724         glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
725         glPushMatrix();
726         glTranslatef(
727                      (f2fl(xc1) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width,
728                      1.0 - (f2fl(yc1) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0);
729         glScalef(f2fl(r1) / last_width, f2fl(r1) / last_height, 1.0);
730         ogl_drawcircle(10 + 2 * (int)(M_PI * f2fl(r1) / 19), GL_LINE_LOOP);
731         glPopMatrix();
732         return 0;
733 }
734 int gr_circle(fix xc1,fix yc1,fix r1){
735         return gr_ucircle(xc1,yc1,r1);
736 }
737
738 bool g3_draw_poly(int nv,g3s_point **pointlist)
739 {
740         int c;
741         r_polyc++;
742         c=grd_curcanv->cv_color;
743 //      glColor3f((gr_palette[c*3]+gr_palette_gamma)/63.0,(gr_palette[c*3+1]+gr_palette_gamma)/63.0,(gr_palette[c*3+2]+gr_palette_gamma)/63.0);
744         OGL_DISABLE(TEXTURE_2D);
745         if (Gr_scanline_darkening_level >= GR_FADE_LEVELS)
746                 glColor3f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c));
747         else
748                 glColor4f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c), 1.0 - (float)Gr_scanline_darkening_level / ((float)GR_FADE_LEVELS - 1.0));
749         glBegin(GL_TRIANGLE_FAN);
750         for (c=0;c<nv;c++){
751         //      glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
752                 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
753         }
754         glEnd();
755         return 0;
756 }
757
758 void gr_upoly_tmap(int nverts, int *vert ){
759                 mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
760 }
761 void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){
762                 mprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called
763 }
764 extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist);
765 bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)
766 {
767         int c;
768         float l;
769         if (tmap_drawer_ptr==draw_tmap_flat){
770 /*              fix average_light=0;
771                 int i;
772                 for (i=0; i<nv; i++)
773                         average_light += uvl_list[i].l;*/
774                 OGL_DISABLE(TEXTURE_2D);
775 //              glmprintf((0,"Gr_scanline_darkening_level=%i %f\n",Gr_scanline_darkening_level,Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
776                 glColor4f(0,0,0,1.0-(Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
777                 //glColor4f(0,0,0,f2fl(average_light/nv));
778                 glBegin(GL_TRIANGLE_FAN);
779                 for (c=0;c<nv;c++){
780 //                      glColor4f(0,0,0,f2fl(uvl_list[c].l));
781 //                      glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
782                         glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
783                 }
784                 glEnd();
785         }else if (tmap_drawer_ptr==draw_tmap){
786                 r_tpolyc++;
787                 /*      if (bm->bm_w !=64||bm->bm_h!=64)
788                         printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
789                 OGL_ENABLE(TEXTURE_2D);
790                 ogl_bindbmtex(bm);
791                 ogl_texwrap(bm->gltexture,GL_REPEAT);
792                 glBegin(GL_TRIANGLE_FAN);
793                 for (c=0;c<nv;c++){
794                         if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
795                                 l=1.0;
796                         }else{
797                                 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
798                                 l=f2fl(uvl_list[c].l);
799                         }
800                         glColor3f(l,l,l);
801                         glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
802                         //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
803                         glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
804                 }
805                 glEnd();
806         }else{
807                 mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
808         }
809         return 0;
810 }
811
812 int active_texture_unit = 0;
813
814 void ogl_setActiveTexture(int t)
815 {
816         if (ogl_arb_multitexture_ok)
817         {
818 #ifdef GL_ARB_multitexture
819                 if (t == 0)
820                         glActiveTextureARB(GL_TEXTURE0_ARB);
821                 else
822                         glActiveTextureARB(GL_TEXTURE1_ARB);
823 #endif
824         }
825         else if (ogl_sgis_multitexture_ok)
826         {
827 #ifdef GL_SGIS_multitexture
828                 if (t == 0)
829                         glSelectTextureSGIS(GL_TEXTURE0_SGIS);
830                 else
831                         glSelectTextureSGIS(GL_TEXTURE1_SGIS);
832 #endif
833         }
834         active_texture_unit = t;
835 }
836
837 void ogl_MultiTexCoord2f(int t, float u, float v)
838 {
839         if (ogl_arb_multitexture_ok)
840         {
841 #ifdef GL_ARB_multitexture
842                 if (t == 0)
843                         glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
844                 else
845                         glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
846 #endif
847         }
848         else if (ogl_sgis_multitexture_ok)
849         {
850 #ifdef GL_SGIS_multitexture
851                 if (t == 0)
852                         glMultiTexCoord2fSGIS(GL_TEXTURE0_SGIS, u, v);
853                 else
854                         glMultiTexCoord2fSGIS(GL_TEXTURE1_SGIS, u, v);
855 #endif
856         }
857 }
858
859 bool g3_draw_tmap_2(int nv, g3s_point **pointlist, g3s_uvl *uvl_list, grs_bitmap *bmbot, grs_bitmap *bm, int orient)
860 {
861 #if ((defined(GL_NV_register_combiners) || defined(GL_NV_texture_env_combine4)) && (defined(GL_ARB_multitexture) || defined(GL_SGIS_multitexture)))
862         if ((/*ogl_nv_register_combiners_ok ||*/ ogl_nv_texture_env_combine4_ok) && (ogl_arb_multitexture_ok || ogl_sgis_multitexture_ok))
863         {
864                 int c;
865                 float l, u1, v1;
866
867                 if (tmap_drawer_ptr != draw_tmap)
868                         Error("WTFF\n");
869
870                 r_tpolyc+=2;
871
872                 //ogl_setActiveTexture(0);
873                 OGL_ENABLE(TEXTURE_2D);
874                 ogl_bindbmtex(bmbot);
875                 ogl_texwrap(bmbot->gltexture, GL_REPEAT);
876                 // GL_MODULATE is fine for texture 0
877
878                 ogl_setActiveTexture(1);
879                 glEnable(GL_TEXTURE_2D);
880                 ogl_bindbmtex(bm);
881                 ogl_texwrap(bm->gltexture,GL_REPEAT);
882
883 #ifdef GL_NV_register_combiners
884                 if (ogl_nv_register_combiners_ok)
885                 {
886                         glEnable(GL_REGISTER_COMBINERS_NV);
887                         glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
888                         // spare0 = tex0 * (1-alpha1) + tex1 * alpha1
889                         glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
890                         glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
891                         glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
892                         glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
893                         glCombinerOutputNV(
894                                            GL_COMBINER0_NV,   //GLenum stage
895                                            GL_RGB,            //GLenum portion,
896                                            GL_DISCARD_NV,     //GLenum abOutput,
897                                            GL_DISCARD_NV,     //GLenum cdOutput,
898                                            GL_SPARE0_NV,      //GLenum sumOutput,
899                                            GL_NONE,           //GLenum scale,
900                                            GL_NONE,           //GLenum bias,
901                                            GL_FALSE,          //GLboolean abDotProduct,
902                                            GL_FALSE,          //GLboolean cdDotProduct,
903                                            GL_FALSE           //GLboolean muxSum
904                                            );
905                         // out = spare0 * color
906                         // ( out = AB + (1-A)C + D )
907                         glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
908                         glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
909                         glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
910                         glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
911
912                         if (bm->bm_flags & BM_FLAG_SUPER_TRANSPARENT)
913                         {
914                                 // out = alpha0*(1-tex1) + alpha1
915                                 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
916                                 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_BLUE);
917                                 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
918                                 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
919                         }
920                         else
921                         {
922                                 // out = alpha0 + alpha1
923                                 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
924                                 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
925                                 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
926                                 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
927                         }
928                         glCombinerOutputNV(
929                                            GL_COMBINER0_NV,   //GLenum stage
930                                            GL_ALPHA,          //GLenum portion,
931                                            GL_DISCARD_NV,     //GLenum abOutput,
932                                            GL_DISCARD_NV,     //GLenum cdOutput,
933                                            GL_SPARE0_NV,      //GLenum sumOutput,
934                                            GL_NONE,           //GLenum scale,
935                                            GL_NONE,           //GLenum bias,
936                                            GL_FALSE,          //GLboolean abDotProduct,
937                                            GL_FALSE,          //GLboolean cdDotProduct,
938                                            GL_FALSE           //GLboolean muxSum
939                                            );
940                         glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
941                 }
942                 else
943 #endif
944                 {
945                         //http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_env_combine4.txt
946                         //only GL_NV_texture_env_combine4 lets us do what we need:
947                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
948
949                         //multiply top texture by color(vertex lighting) and add bottom texture(where alpha says to)
950                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
951
952                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
953                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
954                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE);
955                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_EXT);
956
957                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
958                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
959                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
960                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
961
962                         //add up alpha channels
963                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
964
965                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
966                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
967                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PREVIOUS_EXT);
968                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
969
970                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
971                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
972                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
973                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
974                 }
975
976                 // GL_DECAL works sorta ok but the top texture is fullbright.
977                 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
978
979                 // GL_ARB_texture_env_combine comes close, but doesn't quite make it.
980                 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
981
982                 //// this gives effect like GL_DECAL:
983                 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
984                 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
985                 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
986                 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
987
988
989                 // this properly shades the top texture, but the bottom texture doesn't get through.
990                 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
991                 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
992                 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
993
994
995                 // add up alpha
996                 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
997                 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
998                 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
999
1000                 glBegin(GL_TRIANGLE_FAN);
1001                 for (c=0;c<nv;c++){
1002                         switch(orient){
1003                                 case 1:
1004                                         u1=1.0-f2glf(uvl_list[c].v);
1005                                         v1=f2glf(uvl_list[c].u);
1006                                         break;
1007                                 case 2:
1008                                         u1=1.0-f2glf(uvl_list[c].u);
1009                                         v1=1.0-f2glf(uvl_list[c].v);
1010                                         break;
1011                                 case 3:
1012                                         u1=f2glf(uvl_list[c].v);
1013                                         v1=1.0-f2glf(uvl_list[c].u);
1014                                         break;
1015                                 default:
1016                                         u1=f2glf(uvl_list[c].u);
1017                                         v1=f2glf(uvl_list[c].v);
1018                                         break;
1019                         }
1020                         if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1021                                 l=1.0;
1022                         }else{
1023                                 l=f2fl(uvl_list[c].l);
1024                         }
1025                         glColor3f(l,l,l);
1026                         ogl_MultiTexCoord2f(0, f2glf(uvl_list[c].u), f2glf(uvl_list[c].v));
1027                         ogl_MultiTexCoord2f(1, u1, v1);
1028                         //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1029                         //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1030                         glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1031                 }
1032                 glEnd();
1033                 //ogl_setActiveTexture(1); // still the active texture
1034 #ifdef GL_NV_register_combiners
1035                 if (ogl_nv_register_combiners_ok)
1036                 {
1037                         glDisable(GL_REGISTER_COMBINERS_NV);
1038                 }
1039                 else
1040 #endif
1041                 {
1042                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1043                 }
1044                 glDisable(GL_TEXTURE_2D);
1045                 ogl_setActiveTexture(0);
1046         }
1047         else
1048 #endif
1049         {
1050                 int c;
1051                 float l,u1,v1;
1052
1053                 g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
1054
1055                 r_tpolyc++;
1056                 /*      if (bm->bm_w !=64||bm->bm_h!=64)
1057                         printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
1058                 OGL_ENABLE(TEXTURE_2D);
1059                 ogl_bindbmtex(bm);
1060                 ogl_texwrap(bm->gltexture,GL_REPEAT);
1061                 glBegin(GL_TRIANGLE_FAN);
1062                 for (c=0;c<nv;c++){
1063                         switch(orient){
1064                                 case 1:
1065                                         u1=1.0-f2glf(uvl_list[c].v);
1066                                         v1=f2glf(uvl_list[c].u);
1067                                         break;
1068                                 case 2:
1069                                         u1=1.0-f2glf(uvl_list[c].u);
1070                                         v1=1.0-f2glf(uvl_list[c].v);
1071                                         break;
1072                                 case 3:
1073                                         u1=f2glf(uvl_list[c].v);
1074                                         v1=1.0-f2glf(uvl_list[c].u);
1075                                         break;
1076                                 default:
1077                                         u1=f2glf(uvl_list[c].u);
1078                                         v1=f2glf(uvl_list[c].v);
1079                                         break;
1080                         }
1081                         if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1082                                 l=1.0;
1083                         }else{
1084                                 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
1085                                 l=f2fl(uvl_list[c].l);
1086                         }
1087                         glColor3f(l,l,l);
1088                         glTexCoord2f(u1,v1);
1089                         //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1090                         //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1091                         glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1092                 }
1093                 glEnd();
1094         }
1095         return 0;
1096 }
1097
1098 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
1099 {
1100         //float l=1.0;
1101         vms_vector pv,v1;//,v2;
1102         int i;
1103         r_bitmapc++;
1104         v1.z=0;
1105 //      printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1106 //      printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1107
1108         OGL_ENABLE(TEXTURE_2D);
1109         ogl_bindbmtex(bm);
1110         ogl_texwrap(bm->gltexture,GL_CLAMP);
1111
1112         glBegin(GL_QUADS);
1113         glColor3f(1.0,1.0,1.0);
1114     width = fixmul(width,Matrix_scale.x);       
1115     height = fixmul(height,Matrix_scale.y);     
1116         for (i=0;i<4;i++){
1117 //              g3_rotate_point(&p[i],pos);
1118                 vm_vec_sub(&v1,pos,&View_position);
1119                 vm_vec_rotate(&pv,&v1,&View_matrix);
1120 //              printf(" %f,%f,%f->",f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1121                 switch (i){
1122                         case 0:
1123                                 glTexCoord2f(0.0, 0.0);
1124                                 pv.x+=-width;
1125                                 pv.y+=height;
1126                                 break;
1127                         case 1:
1128                                 glTexCoord2f(bm->gltexture->u, 0.0);
1129                                 pv.x+=width;
1130                                 pv.y+=height;
1131                                 break;
1132                         case 2:
1133                                 glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
1134                                 pv.x+=width;
1135                                 pv.y+=-height;
1136                                 break;
1137                         case 3:
1138                                 glTexCoord2f(0.0, bm->gltexture->v);
1139                                 pv.x+=-width;
1140                                 pv.y+=-height;
1141                                 break;
1142                 }
1143 //              vm_vec_rotate(&v2,&v1,&View_matrix);
1144 //              vm_vec_sub(&v1,&v2,&pv);
1145                 //vm_vec_sub(&v1,&pv,&v2);
1146 //              vm_vec_sub(&v2,&pv,&v1);
1147                 glVertex3f(f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1148 //              printf("%f,%f,%f ",f2glf(v1.x),f2glf(v1.y),-f2glf(v1.z));
1149         }
1150         glEnd();
1151 //      printf("\n");
1152
1153         return 0;
1154 }
1155
1156 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
1157 {
1158         GLfloat xo,yo,xf,yf;
1159         GLfloat u1,u2,v1,v2;
1160         r_ubitmapc++;
1161         x+=grd_curcanv->cv_bitmap.bm_x;
1162         y+=grd_curcanv->cv_bitmap.bm_y;
1163         xo=x/(float)last_width;
1164         xf=(bm->bm_w+x)/(float)last_width;
1165         yo=1.0-y/(float)last_height;
1166         yf=1.0-(bm->bm_h+y)/(float)last_height;
1167
1168 //      printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1169 //      printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1170
1171 /*              glEnABLE(ALPHA_TEST);
1172         glAlphaFunc(GL_GREATER,0.0);*/
1173
1174         OGL_ENABLE(TEXTURE_2D);
1175         ogl_bindbmtex(bm);
1176         ogl_texwrap(bm->gltexture,GL_CLAMP);
1177         
1178         if (bm->bm_x==0){
1179                 u1=0;
1180                 if (bm->bm_w==bm->gltexture->w)
1181                         u2=bm->gltexture->u;
1182                 else
1183                         u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1184         }else {
1185                 u1=bm->bm_x/(float)bm->gltexture->tw;
1186                 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1187         }
1188         if (bm->bm_y==0){
1189                 v1=0;
1190                 if (bm->bm_h==bm->gltexture->h)
1191                         v2=bm->gltexture->v;
1192                 else
1193                         v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1194         }else{
1195                 v1=bm->bm_y/(float)bm->gltexture->th;
1196                 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1197         }
1198
1199         glBegin(GL_QUADS);
1200         if (c<0)
1201                 glColor3f(1.0,1.0,1.0);
1202         else
1203                 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
1204         glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1205         glTexCoord2f(u2, v1); glVertex2f(xf, yo);
1206         glTexCoord2f(u2, v2); glVertex2f(xf, yf);
1207         glTexCoord2f(u1, v2); glVertex2f(xo, yf);
1208         glEnd();
1209 //      glDisABLE(ALPHA_TEST);
1210         
1211         return 0;
1212 }
1213 bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){
1214         return ogl_ubitmapm_c(x,y,bm,-1);
1215 //      return ogl_ubitblt(bm->bm_w,bm->bm_h,x,y,0,0,bm,NULL);
1216 }
1217 #if 0
1218 //also upsidedown, currently.
1219 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1220 {
1221         GLfloat xo,yo;//,xs,ys;
1222         glmprintf((0,"ogl_ubitblt(w=%i,h=%i,dx=%i,dy=%i,sx=%i,sy=%i,src=%p,dest=%p\n",w,h, dx, dy,sx, sy,  src,dest));
1223         
1224         dx+=dest->bm_x;
1225         dy+=dest->bm_y;
1226         
1227         xo=dx/(float)last_width;
1228 //      xo=dx/(float)grd_curscreen->sc_w;
1229 //      xs=w/(float)last_width;
1230         //yo=1.0-dy/(float)last_height;
1231         yo=1.0-(dy+h)/(float)last_height;
1232 //      ys=h/(float)last_height;
1233         
1234 //      OGL_ENABLE(TEXTURE_2D);
1235         
1236         OGL_DISABLE(TEXTURE_2D);
1237         glRasterPos2f(xo,yo);
1238         ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h,GL_RGBA);
1239         glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);
1240         glRasterPos2f(0,0);
1241         
1242         return 0;
1243 }
1244 #else
1245 bool ogl_ubitblt_i(int dw,int dh,int dx,int dy, int sw, int sh, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1246 {
1247         GLfloat xo,yo,xs,ys;
1248         GLfloat u1,v1;//,u2,v2;
1249         ogl_texture tex;
1250 //      unsigned char *oldpal;
1251         r_ubitbltc++;
1252
1253         ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA);
1254         tex.prio = 0.0;
1255         tex.lw=src->bm_rowsize;
1256
1257 /*      if (w==src->bm_w && sx==0){
1258                 u1=0;u2=src->glu;
1259         }else{
1260                 u1=sx/(float)src->bm_w*src->glu;
1261                 u2=w/(float)src->bm_w*src->glu+u1;
1262         }
1263         if (h==src->bm_h && sy==0){
1264                 v1=0;v2=src->glv;
1265         }else{
1266                 v1=sy/(float)src->bm_h*src->glv;
1267                 v2=h/(float)src->bm_h*src->glv+v1;
1268         }*/
1269         u1=v1=0;
1270         
1271         dx+=dest->bm_x;
1272         dy+=dest->bm_y;
1273         xo=dx/(float)last_width;
1274         xs=dw/(float)last_width;
1275         yo=1.0-dy/(float)last_height;
1276         ys=dh/(float)last_height;
1277         
1278         OGL_ENABLE(TEXTURE_2D);
1279         
1280 //      oldpal=ogl_pal;
1281         ogl_pal=gr_current_pal;
1282         ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags, 0);
1283 //      ogl_pal=oldpal;
1284         ogl_pal=gr_palette;
1285         OGL_BINDTEXTURE(tex.handle);
1286         
1287         ogl_texwrap(&tex,GL_CLAMP);
1288
1289         glBegin(GL_QUADS);
1290         glColor3f(1.0,1.0,1.0);
1291         glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1292         glTexCoord2f(tex.u, v1); glVertex2f(xo+xs, yo);
1293         glTexCoord2f(tex.u, tex.v); glVertex2f(xo+xs, yo-ys);
1294         glTexCoord2f(u1, tex.v); glVertex2f(xo, yo-ys);
1295         glEnd();
1296         ogl_freetexture(&tex);
1297         return 0;
1298 }
1299 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1300         return ogl_ubitblt_i(w,h,dx,dy,w,h,sx,sy,src,dest);
1301 }
1302 #endif
1303 bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1304 #if 1
1305         unsigned char *d,*s;
1306         int i,j;
1307         int w1,h1;
1308 //      w1=w;h1=h;
1309         w1=grd_curscreen->sc_w;h1=grd_curscreen->sc_h;
1310         if (w1*h1*3>OGLTEXBUFSIZE)
1311                 Error("ogl_ubitblt_tolinear: screen res larger than OGLTEXBUFSIZE\n");
1312
1313         if (ogl_readpixels_ok>0){
1314                 OGL_DISABLE(TEXTURE_2D);
1315                 glReadBuffer(GL_FRONT);
1316                 glReadPixels(0,0,w1,h1,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1317 //              glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1318 //              glReadPixels(sx,sy,w+sx,h+sy,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1319         }else
1320                 memset(texbuf,0,w1*h1*3);
1321         sx+=src->bm_x;
1322         sy+=src->bm_y;
1323         for (i=0;i<h;i++){
1324                 d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1325                 s=texbuf+((h1-(i+sy+1))*w1+sx)*3;
1326                 for (j=0;j<w;j++){
1327                         *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1328                         s+=3;
1329                         d++;
1330                 }
1331         }
1332 #else
1333         int i,j,c=0;
1334         unsigned char *d,*s,*e;
1335         if (w*h*3>OGLTEXBUFSIZE)
1336                 Error("ogl_ubitblt_tolinear: size larger than OGLTEXBUFSIZE\n");
1337         sx+=src->bm_x;
1338         sy+=src->bm_y;
1339 #if 1//also seems to cause a mess.  need to look into it a bit more..
1340         if (ogl_readpixels_ok>0){
1341                 OGL_DISABLE(TEXTURE_2D);
1342                 glReadBuffer(GL_FRONT);
1343 //              glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1344                 glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1345         }else
1346 #endif
1347                 memset(texbuf,0,w*h*3);
1348 //      d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1349         d=dest->bm_data+dx+dy*dest->bm_rowsize;
1350         for (i=0;i<h;i++){
1351                 s=texbuf+w*(h-(i+1))*3;
1352 //              s=texbuf+w*i*3;
1353                 if (s<texbuf){Error("blah1\n");}
1354                 if (d<dest->bm_data){Error("blah3\n");}
1355 //              d=dest->bm_data+(i*dest->bm_rowsize);
1356
1357                 e=d;
1358                 for (j=0;j<w;j++){
1359                         if (s>texbuf+w*h*3-3){Error("blah2\n");}
1360                         if (d>dest->bm_data+dest->bm_rowsize*(h+dy)+dx  ){Error("blah4\n");}
1361                         *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1362                         s+=3;
1363                         d++;
1364                         c++;
1365                 }
1366                 d=e;
1367                 d+=dest->bm_rowsize;
1368         }
1369         glmprintf((0,"c=%i w*h=%i\n",c,w*h));
1370 #endif
1371         return 0;
1372 }
1373
1374 bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1375 #if 0 //just seems to cause a mess.
1376         GLfloat xo,yo;//,xs,ys;
1377         
1378         dx+=dest->bm_x;
1379         dy+=dest->bm_y;
1380         
1381 //      xo=dx/(float)last_width;
1382         xo=dx/(float)grd_curscreen->sc_w;
1383 //      yo=1.0-(dy+h)/(float)last_height;
1384         yo=1.0-(dy+h)/(float)grd_curscreen->sc_h;
1385         sx+=src->bm_x;
1386         sy+=src->bm_y;
1387         OGL_DISABLE(TEXTURE_2D);
1388         glReadBuffer(GL_FRONT);
1389         glRasterPos2f(xo,yo);
1390 //      glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1391         glCopyPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_COLOR);
1392         glRasterPos2f(0,0);
1393 #endif
1394         return 0;
1395 }
1396
1397 grs_canvas *offscreen_save_canv = NULL, *offscreen_canv = NULL;
1398
1399 void ogl_start_offscreen_render(int x, int y, int w, int h)
1400 {
1401         if (offscreen_canv)
1402                 Error("ogl_start_offscreen_render: offscreen_canv!=NULL");
1403         offscreen_save_canv = grd_curcanv;
1404         offscreen_canv = gr_create_sub_canvas(grd_curcanv, x, y, w, h);
1405         gr_set_current_canvas(offscreen_canv);
1406         glDrawBuffer(GL_BACK);
1407 }
1408 void ogl_end_offscreen_render(void)
1409 {
1410         int y;
1411
1412         if (!offscreen_canv)
1413                 Error("ogl_end_offscreen_render: no offscreen_canv");
1414
1415         glDrawBuffer(GL_FRONT);
1416         glReadBuffer(GL_BACK);
1417         OGL_DISABLE(TEXTURE_2D);
1418
1419         y = last_height - offscreen_canv->cv_bitmap.bm_y - offscreen_canv->cv_bitmap.bm_h;
1420         glRasterPos2f(offscreen_canv->cv_bitmap.bm_x/(float)last_width, y/(float)last_height);
1421         glCopyPixels(offscreen_canv->cv_bitmap.bm_x, y,
1422                      offscreen_canv->cv_bitmap.bm_w,
1423                  offscreen_canv->cv_bitmap.bm_h, GL_COLOR);
1424
1425         gr_free_sub_canvas(offscreen_canv);
1426         gr_set_current_canvas(offscreen_save_canv);
1427         offscreen_canv=NULL;
1428 }
1429
1430 void ogl_start_frame(void){
1431         r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;
1432 //      gl_badtexture=500;
1433
1434         OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);
1435         glClearColor(0.0, 0.0, 0.0, 0.0);
1436 //      glEnable(GL_ALPHA_TEST);
1437 //      glAlphaFunc(GL_GREATER,0.01);
1438         glShadeModel(GL_SMOOTH);
1439         glMatrixMode(GL_PROJECTION);
1440         glLoadIdentity();//clear matrix
1441         //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1442         //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),0.01,1000000.0);
1443         gluPerspective(90.0,1.0,0.01,1000000.0);
1444         //gluPerspective(90.0,(GLfloat)(Canvas_width*3)/(GLfloat)(Canvas_height*4),0.01,1000000.0);
1445 //      gluPerspective(75.0,(GLfloat)Canvas_width/(GLfloat)Canvas_height,1.0,1000000.0);
1446         glMatrixMode(GL_MODELVIEW);
1447         glLoadIdentity();//clear matrix
1448         glEnable(GL_BLEND);
1449         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1450 //      glDisABLE(DITHER);
1451 //      glScalef(1.0,1.0,-1.0);
1452 //      glScalef(1.0,1.0,-1.0);
1453 //      glPushMatrix();
1454         
1455 //      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1456 //      OGL_TEXENV(GL_TEXTURE_ENV_MODE,GL_MODULATE);
1457 //      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1458 //      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1459 //      OGL_TEXPARAM(GL_TEXTURE_MAG_FILTER,GL_texmagfilt);
1460 //      OGL_TEXPARAM(GL_TEXTURE_MIN_FILTER,GL_texminfilt);
1461 //      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1462 //      glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1463 }
1464 #ifndef NMONO
1465 void merge_textures_stats(void);
1466 #endif
1467 void ogl_end_frame(void){
1468 //      OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);
1469         OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1470 #ifndef NMONO
1471 //      merge_textures_stats();
1472 //      ogl_texture_stats();
1473 #endif
1474 //      glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1475         glMatrixMode(GL_PROJECTION);
1476         glLoadIdentity();//clear matrix
1477         glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
1478         glMatrixMode(GL_MODELVIEW);
1479         glLoadIdentity();//clear matrix
1480 //      glDisABLE(BLEND);
1481         //glDisABLE(ALPHA_TEST);
1482         //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1483 //      ogl_swap_buffers();//platform specific code
1484 //      glClear(GL_COLOR_BUFFER_BIT);
1485 }
1486 void ogl_swap_buffers(void){
1487         ogl_clean_texture_cache();
1488         if (gr_renderstats){
1489                 gr_printf(5,GAME_FONT->ft_h*13+3*13,"%i flat %i tex %i sprites %i bitmaps",r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc);
1490 //      glmprintf((0,"ogl_end_frame: %i polys, %i tmaps, %i sprites, %i bitmaps, %i bitblts, %i pixels\n",r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc));//we need to do it here because some things get drawn after end_frame
1491         }
1492         ogl_do_palfx();
1493         ogl_swap_buffers_internal();
1494         glClear(GL_COLOR_BUFFER_BIT);
1495 }
1496
1497 void ogl_init_shared_palette(void)
1498 {
1499 #ifdef GL_EXT_paletted_texture
1500         if (ogl_shared_palette_ok)
1501         {
1502                 int i;
1503
1504                 glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1505                 //glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, ogl_pal);
1506
1507                 for (i = 0; i < 256; i++)
1508                 {
1509                         if (i == 254)
1510                         {
1511                                 texbuf[i * 4] = 255;
1512                                 texbuf[i * 4 + 1] = 255;
1513                                 texbuf[i * 4 + 2] = 255;
1514                                 texbuf[i * 4 + 3] = 0;
1515                         }
1516                         else if (i == 255)
1517                         {
1518                                 texbuf[i * 4] = 0;
1519                                 texbuf[i * 4 + 1] = 0;
1520                                 texbuf[i * 4 + 2] = 0;
1521                                 texbuf[i * 4 + 3] = 0;
1522                         }
1523                         else
1524                         {
1525                                 texbuf[i * 4] = gr_current_pal[i * 3] * 4;
1526                                 texbuf[i * 4 + 1] = gr_current_pal[i * 3 + 1] * 4;
1527                                 texbuf[i * 4 + 2] = gr_current_pal[i * 3 + 2] * 4;
1528                                 texbuf[i * 4 + 3] = 255;
1529                         }
1530                 }
1531                 glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
1532         }
1533 #endif
1534 }
1535
1536 int tex_format_supported(int iformat,int format){
1537         switch (iformat){
1538                 case GL_INTENSITY4:
1539                         if (!ogl_intensity4_ok) return 0; break;
1540                 case GL_LUMINANCE4_ALPHA4:
1541                         if (!ogl_luminance4_alpha4_ok) return 0; break;
1542                 case GL_RGBA2:
1543                         if (!ogl_rgba2_ok) return 0; break;
1544         }
1545         if (ogl_gettexlevelparam_ok){
1546                 GLint internalFormat;
1547                 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, iformat, 64, 64, 0,
1548                                 format, GL_UNSIGNED_BYTE, texbuf);//NULL?
1549                 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
1550                                 GL_TEXTURE_INTERNAL_FORMAT,
1551                                 &internalFormat);
1552                 return (internalFormat==iformat);
1553         }else
1554                 return 1;
1555 }
1556
1557 //little hack to find the largest or equal multiple of 2 for a given number
1558 int pow2ize(int x){
1559         int i;
1560
1561         for (i = 1; i <= 4096; i *= 2)
1562                 if (x<=i) return i;
1563         return i;
1564 }
1565
1566 //GLubyte texbuf[512*512*4];
1567 GLubyte texbuf[OGLTEXBUFSIZE];
1568
1569 void ogl_filltexbuf(unsigned char *data, GLubyte *texp, int truewidth, int width, int height, int dxo, int dyo, int twidth, int theight, int type, int bm_flags, int data_format)
1570 {
1571 //      GLushort *tex=(GLushort *)texp;
1572         int x,y,c,i;
1573         if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
1574                 Error("texture toobig %i %i",twidth,theight);
1575
1576         i=0;
1577         for (y=0;y<theight;y++){
1578                 i=dxo+truewidth*(y+dyo);
1579                 for (x=0;x<twidth;x++){
1580                         if (x<width && y<height)
1581                                 if (data_format)
1582                                 {
1583                                         int j;
1584
1585                                         for (j = 0; j < data_format; ++j)
1586                                                 (*(texp++)) = data[i * data_format + j];
1587                                         i++;
1588                                         continue;
1589                                 }
1590                                 else
1591                                         c = data[i++];
1592                         else
1593                                 c = 256; // fill the pad space with transparency (or blackness)
1594                         if (c == 254 && (bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1595                         {
1596                                 switch (type)
1597                                 {
1598                                 case GL_LUMINANCE_ALPHA:
1599                                         (*(texp++)) = 255;
1600                                         (*(texp++)) = 0;
1601                                         break;
1602                                 case GL_RGBA:
1603                                         (*(texp++)) = 255;
1604                                         (*(texp++)) = 255;
1605                                         (*(texp++)) = 255;
1606                                         (*(texp++)) = 0; // transparent pixel
1607                                         break;
1608                                 case GL_COLOR_INDEX:
1609                                         (*(texp++)) = c;
1610                                         break;
1611                                 default:
1612                                         Error("ogl_filltexbuf unhandled super-transparent texformat\n");
1613                                         break;
1614                                 }
1615                         }
1616                         else if ((c == 255 && (bm_flags & BM_FLAG_TRANSPARENT)) || c == 256)
1617                         {
1618                                 switch (type){
1619                                         case GL_LUMINANCE:
1620                                                 (*(texp++))=0;
1621                                                 break;
1622                                         case GL_LUMINANCE_ALPHA:
1623                                                 (*(texp++))=0;
1624                                                 (*(texp++))=0;
1625                                                 break;
1626                                         case GL_RGB:
1627                                                 (*(texp++)) = 0;
1628                                                 (*(texp++)) = 0;
1629                                                 (*(texp++)) = 0;
1630                                                 break;
1631                                         case GL_RGBA:
1632                                                 (*(texp++))=0;
1633                                                 (*(texp++))=0;
1634                                                 (*(texp++))=0;
1635                                                 (*(texp++))=0;//transparent pixel
1636                                                 break;
1637                                         case GL_COLOR_INDEX:
1638                                                 (*(texp++)) = c;
1639                                                 break;
1640                                         default:
1641                                                 Error("ogl_filltexbuf unknown texformat\n");
1642                                                 break;
1643                                 }
1644                         }else{
1645                                 switch (type){
1646                                         case GL_LUMINANCE://these could prolly be done to make the intensity based upon the intensity of the resulting color, but its not needed for anything (yet?) so no point. :)
1647                                                 (*(texp++))=255;
1648                                                 break;
1649                                         case GL_LUMINANCE_ALPHA:
1650                                                 (*(texp++))=255;
1651                                                 (*(texp++))=255;
1652                                                 break;
1653                                         case GL_RGB:
1654                                                 (*(texp++)) = ogl_pal[c * 3] * 4;
1655                                                 (*(texp++)) = ogl_pal[c * 3 + 1] * 4;
1656                                                 (*(texp++)) = ogl_pal[c * 3 + 2] * 4;
1657                                                 break;
1658                                         case GL_RGBA:
1659                                                 //(*(texp++))=gr_palette[c*3]*4;
1660                                                 //(*(texp++))=gr_palette[c*3+1]*4;
1661                                                 //(*(texp++))=gr_palette[c*3+2]*4;
1662                                                 (*(texp++))=ogl_pal[c*3]*4;
1663                                                 (*(texp++))=ogl_pal[c*3+1]*4;
1664                                                 (*(texp++))=ogl_pal[c*3+2]*4;
1665                                                 (*(texp++))=255;//not transparent
1666                                                 //                              (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
1667                                                 break;
1668                                         case GL_COLOR_INDEX:
1669                                                 (*(texp++)) = c;
1670                                                 break;
1671                                         default:
1672                                                 Error("ogl_filltexbuf unknown texformat\n");
1673                                                 break;
1674                                 }
1675                         }
1676                 }
1677         }
1678 }
1679
1680 int tex_format_verify(ogl_texture *tex){
1681         while (!tex_format_supported(tex->internalformat,tex->format)){
1682                 glmprintf((0,"tex format %x not supported",tex->internalformat));
1683                 switch (tex->internalformat){
1684                         case GL_INTENSITY4:
1685                                 if (ogl_luminance4_alpha4_ok){
1686                                         tex->internalformat=GL_LUMINANCE4_ALPHA4;
1687                                         tex->format=GL_LUMINANCE_ALPHA;
1688                                         break;
1689                                 }//note how it will fall through here if the statement is false
1690                         case GL_LUMINANCE4_ALPHA4:
1691                                 if (ogl_rgba2_ok){
1692                                         tex->internalformat=GL_RGBA2;
1693                                         tex->format=GL_RGBA;
1694                                         break;
1695                                 }//note how it will fall through here if the statement is false
1696                         case GL_RGBA2:
1697 #if defined(__APPLE__) && defined(__MACH__)
1698                         case GL_RGB8:   // Quartz doesn't support RGB only
1699 #endif
1700                                 tex->internalformat = ogl_rgba_internalformat;
1701                                 tex->format=GL_RGBA;
1702                                 break;
1703                         default:
1704                                 mprintf((0,"...no tex format to fall back on\n"));
1705                                 return 1;
1706                 }
1707                 glmprintf((0,"...falling back to %x\n",tex->internalformat));
1708         }
1709         return 0;
1710 }
1711 void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){
1712         int u;
1713         if (tex->tw!=w || tex->th!=h){
1714                 u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h);
1715                 glmprintf((0,"shrunken texture?\n"));
1716         }else
1717                 u=tex->w*tex->h;
1718         if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
1719                 tex->bytes=((float)w*h*dbits)/8.0;
1720                 tex->bytesu=((float)u*dbits)/8.0;
1721         }else{
1722                 tex->bytes=((float)w*h*bits)/8.0;
1723                 tex->bytesu=((float)u*bits)/8.0;
1724         }
1725         glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes));
1726 }
1727 void tex_set_size(ogl_texture *tex){
1728         GLint w,h;
1729         int bi=16,a=0;
1730         if (ogl_gettexlevelparam_ok){
1731                 GLint t;
1732                 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w);
1733                 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h);
1734                 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t;
1735                 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t;
1736                 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t;
1737                 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t;
1738                 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t;
1739                 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t;
1740 #ifdef GL_EXT_paletted_texture
1741                 if (ogl_paletted_texture_ok)
1742                 {
1743                         glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INDEX_SIZE_EXT, &t);
1744                         a += t;
1745                 }
1746 #endif
1747         }else{
1748                 w=tex->tw;
1749                 h=tex->th;
1750         }
1751         switch (tex->format){
1752                 case GL_LUMINANCE:
1753                         bi=8;
1754                         break;
1755                 case GL_LUMINANCE_ALPHA:
1756                         bi=8;
1757                         break;
1758                 case GL_RGB:
1759                 case GL_RGBA:
1760                         bi=16;
1761                         break;
1762                 case GL_COLOR_INDEX:
1763                         bi = 8;
1764                         break;
1765                 default:
1766                         Error("tex_set_size unknown texformat\n");
1767                         break;
1768         }
1769         tex_set_size1(tex,bi,a,w,h);
1770 }
1771 //loads a palettized bitmap into a ogl RGBA texture.
1772 //Sizes and pads dimensions to multiples of 2 if necessary.
1773 //In theory this could be a problem for repeating textures, but all real
1774 //textures (not sprites, etc) in descent are 64x64, so we are ok.
1775 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
1776 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format)
1777 {
1778 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
1779 //      int internalformat=GL_RGBA;
1780 //      int format=GL_RGBA;
1781         //int filltype=0;
1782         tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
1783 //      tex->tw=tex->w;tex->th=tex->h;//feeling lucky?
1784         
1785         if(gr_badtexture>0) return;
1786
1787         if (tex_format_verify(tex))
1788                 return;
1789
1790         //calculate u/v values that would make the resulting texture correctly sized
1791         tex->u=(float)tex->w/(float)tex->tw;
1792         tex->v=(float)tex->h/(float)tex->th;
1793
1794 #ifdef GL_EXT_paletted_texture
1795         if (ogl_shared_palette_ok && data_format == 0 && (tex->format == GL_RGBA || tex->format == GL_RGB) &&
1796                 !(tex->wantmip && GL_needmipmaps) // gluBuild2DMipmaps doesn't support paletted textures.. this could be worked around be generating our own mipmaps, but thats too much trouble at the moment.
1797                 )
1798         {
1799                 // descent makes palette entries 254 and 255 both do double duty, depending upon the setting of BM_FLAG_SUPER_TRANSPARENT and BM_FLAG_TRANSPARENT.
1800                 // So if the texture doesn't have BM_FLAG_TRANSPARENT set, yet uses index 255, we cannot use the palette for it since that color would be incorrect. (this case is much less common than transparent textures, hence why we don't exclude those instead.)
1801                 // We don't handle super transparent textures with ogl yet, so we don't bother checking that here.
1802                 int usesthetransparentindexcolor = 0, usesthesupertransparentindexcolor = 0;
1803
1804                 if (!(bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1805                 {
1806                         int i;
1807
1808                         for (i = 0; i < tex->w * tex->h; ++i)
1809                                 if (data[i] == 254)
1810                                         usesthesupertransparentindexcolor += 1;
1811                 }
1812                 if (!(bm_flags & BM_FLAG_TRANSPARENT))
1813                 {
1814                         int i;
1815
1816                         for (i=0; i < tex->w * tex->h; ++i)
1817                                 if (data[i] == 255)
1818                                         usesthetransparentindexcolor += 1;
1819                 }
1820                 if (!usesthetransparentindexcolor && !usesthesupertransparentindexcolor)
1821                 {
1822                         tex->internalformat = GL_COLOR_INDEX8_EXT;
1823                         tex->format = GL_COLOR_INDEX;
1824                 }
1825                 //else
1826                 //      printf("bm data=%p w=%i h=%i transparent:%i supertrans:%i\n", data, tex->w, tex->h, usesthetransparentindexcolor, usesthesupertransparentindexcolor);
1827         }
1828 #endif
1829
1830         //      if (width!=twidth || height!=theight)
1831         //              glmprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
1832         ogl_filltexbuf(data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags, data_format);
1833
1834         // Generate OpenGL texture IDs.
1835         glGenTextures(1, &tex->handle);
1836
1837         //set priority
1838         glPrioritizeTextures(1,&tex->handle,&tex->prio);
1839         
1840         // Give our data to OpenGL.
1841
1842         OGL_BINDTEXTURE(tex->handle);
1843
1844         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1845         if (tex->wantmip){
1846                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1847                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1848                 if (ogl_ext_texture_filter_anisotropic_ok && GL_texanisofilt)
1849                         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_texanisofilt);
1850         }
1851         else
1852         {
1853                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1854                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1855         }
1856 //      domipmap=0;//mipmaps aren't used in GL_NEAREST anyway, and making the mipmaps is pretty slow
1857         //however, if texturing mode becomes an ingame option, they would need to be made regardless, so it could switch to them later.  OTOH, texturing mode could just be made a command line arg.
1858
1859         if (tex->wantmip && GL_needmipmaps)
1860                 gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
1861                                 tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
1862         else
1863                 glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
1864                         tex->tw, tex->th, 0, tex->format, // RGBA textures.
1865                         GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
1866                         texbuf);
1867         
1868         tex_set_size(tex);
1869
1870         r_texcount++; 
1871         glmprintf((0,"ogl_loadtexture(%p,%i,%i,%ix%i,%p):%i u=%f v=%f b=%i bu=%i (%i)\n",data,tex->tw,tex->th,dxo,dyo,tex,tex->handle,tex->u,tex->v,tex->bytes,tex->bytesu,r_texcount));
1872
1873 }
1874
1875 unsigned char decodebuf[512*512];
1876
1877 void ogl_loadbmtexture_f(grs_bitmap *bm, int flags)
1878 {
1879         unsigned char *buf;
1880 #ifdef HAVE_LIBPNG
1881         char *bitmapname;
1882 #endif
1883
1884         while (bm->bm_parent)
1885                 bm=bm->bm_parent;
1886         if (bm->gltexture && bm->gltexture->handle > 0)
1887                 return;
1888         buf=bm->bm_data;
1889 #ifdef HAVE_LIBPNG
1890         if ((bitmapname = piggy_game_bitmap_name(bm)))
1891         {
1892                 char filename[64];
1893                 png_data pdata;
1894
1895                 sprintf(filename, "textures/%s.png", bitmapname);
1896                 if (read_png(filename, &pdata))
1897                 {
1898                         printf("%s: %ux%ux%i p=%i(%i) c=%i a=%i chans=%i\n", filename, pdata.width, pdata.height, pdata.depth, pdata.paletted, pdata.num_palette, pdata.color, pdata.alpha, pdata.channels);
1899                         if (pdata.depth == 8 && pdata.color)
1900                         {
1901                                 if (bm->gltexture == NULL)
1902                                         ogl_init_texture(bm->gltexture = ogl_get_free_texture(), pdata.width, pdata.height, flags | ((pdata.alpha || bm->bm_flags & BM_FLAG_TRANSPARENT) ? OGL_FLAG_ALPHA : 0));
1903                                 ogl_loadtexture(pdata.data, 0, 0, bm->gltexture, bm->bm_flags, pdata.paletted ? 0 : pdata.channels);
1904                                 free(pdata.data);
1905                                 if (pdata.palette)
1906                                         free(pdata.palette);
1907                                 return;
1908                         }
1909                         else
1910                         {
1911                                 printf("%s: unsupported texture format: must be rgb, rgba, or paletted, and depth 8\n", filename);
1912                                 free(pdata.data);
1913                                 if (pdata.palette)
1914                                         free(pdata.palette);
1915                         }
1916                 }
1917         }
1918 #endif
1919         if (bm->gltexture == NULL){
1920                 ogl_init_texture(bm->gltexture = ogl_get_free_texture(), bm->bm_w, bm->bm_h, flags | ((bm->bm_flags & BM_FLAG_TRANSPARENT) ? OGL_FLAG_ALPHA : 0));
1921         }
1922         else {
1923                 if (bm->gltexture->handle>0)
1924                         return;
1925                 if (bm->gltexture->w==0){
1926                         bm->gltexture->lw=bm->bm_w;
1927                         bm->gltexture->w=bm->bm_w;
1928                         bm->gltexture->h=bm->bm_h;
1929                 }
1930         }
1931         if (bm->bm_flags & BM_FLAG_RLE){
1932                 unsigned char * dbits;
1933                 unsigned char * sbits;
1934                 int i, data_offset;
1935
1936                 data_offset = 1;
1937                 if (bm->bm_flags & BM_FLAG_RLE_BIG)
1938                         data_offset = 2;
1939
1940                 sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)];
1941                 dbits = decodebuf;
1942
1943                 for (i=0; i < bm->bm_h; i++ )    {
1944                         gr_rle_decode(sbits,dbits);
1945                         if ( bm->bm_flags & BM_FLAG_RLE_BIG )
1946                                 sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)])));
1947                         else
1948                                 sbits += (int)bm->bm_data[4+i];
1949                         dbits += bm->bm_w;
1950                 }
1951                 buf=decodebuf;
1952         }
1953         ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags, 0);
1954 }
1955
1956 void ogl_loadbmtexture(grs_bitmap *bm)
1957 {
1958         ogl_loadbmtexture_f(bm, OGL_FLAG_MIPMAP);
1959 }
1960
1961 void ogl_freetexture(ogl_texture *gltexture)
1962 {
1963         if (gltexture->handle>0) {
1964                 r_texcount--;
1965                 glmprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
1966                 glDeleteTextures( 1, &gltexture->handle );
1967 //              gltexture->handle=0;
1968                 ogl_reset_texture(gltexture);
1969         }
1970 }
1971 void ogl_freebmtexture(grs_bitmap *bm){
1972         if (bm->gltexture){
1973                 ogl_freetexture(bm->gltexture);
1974                 bm->gltexture=NULL;
1975 //              r_texcount--;
1976 //              glmprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
1977 //              glDeleteTextures( 1, &bm->gltexture );
1978 //              bm->gltexture=-1;
1979         }
1980 }