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