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