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