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