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