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