1 /* $Id: ogl.c,v 1.29 2004-05-22 21:48:36 btb Exp $ */
4 * Graphics support functions for OpenGL.
19 #if defined(__APPLE__) && defined(__MACH__)
20 #include <OpenGL/gl.h>
21 #include <OpenGL/glu.h>
31 #include "../../3d/globvars.h"
50 //change to 1 for lots of spew.
52 #define glmprintf(a) mprintf(a)
61 #if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__)
62 #define cosf(a) cos(a)
63 #define sinf(a) sin(a)
66 unsigned char *ogl_pal=gr_palette;
68 int GL_texmagfilt=GL_NEAREST;
69 int GL_texminfilt=GL_NEAREST;
70 float GL_texanisofilt = 0;
73 int last_width=-1,last_height=-1;
74 int GL_TEXTURE_2D_enabled=-1;
75 int GL_texclamp_enabled=-1;
77 extern int gr_badtexture;
78 int r_texcount = 0, r_cachedtexcount = 0;
79 int ogl_alttexmerge=1;//merge textures by just printing the seperate textures?
80 int ogl_rgba_internalformat = GL_RGBA8;
81 int ogl_rgb_internalformat = GL_RGB8;
82 int ogl_intensity4_ok=1;
83 int ogl_luminance4_alpha4_ok=1;
85 int ogl_readpixels_ok=1;
86 int ogl_gettexlevelparam_ok=1;
87 #ifdef GL_ARB_multitexture
88 int ogl_arb_multitexture_ok=0;
90 #ifdef GL_SGIS_multitexture
91 int ogl_sgis_multitexture_ok=0;
93 int ogl_nv_texture_env_combine4_ok = 0;
94 #ifdef GL_NV_register_combiners
95 int ogl_nv_register_combiners_ok = 0;
97 int ogl_ext_texture_filter_anisotropic_ok = 0;
98 #ifdef GL_EXT_paletted_texture
99 int ogl_shared_palette_ok = 0;
100 int ogl_paletted_texture_ok = 0;
104 int cross_lh[2]={0,0};
105 int primary_lh[3]={0,0,0};
106 int secondary_lh[5]={0,0,0,0,0};
109 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
110 else if(a!=lastbound) {glBindTexture(GL_TEXTURE_2D, a);lastbound=a;}*/
111 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
112 else glBindTexture(GL_TEXTURE_2D, a);
115 ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE];
116 int ogl_texture_list_cur;
118 /* some function prototypes */
120 //#define OGLTEXBUFSIZE (1024*1024*4)
121 #define OGLTEXBUFSIZE (2048*2048*4)
122 extern GLubyte texbuf[OGLTEXBUFSIZE];
123 //void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int width,int height,int twidth,int theight);
124 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);
125 void ogl_loadbmtexture(grs_bitmap *bm);
126 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,intdyo , int *texid,float *u,float *v,char domipmap,float prio);
127 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags);
128 void ogl_freetexture(ogl_texture *gltexture);
129 void ogl_do_palfx(void);
131 void ogl_init_texture_stats(ogl_texture* t){
132 t->prio=0.3;//default prio
136 void ogl_init_texture(ogl_texture* t, int w, int h, int flags)
139 if (flags & OGL_FLAG_NOCOLOR)
141 // use GL_INTENSITY instead of GL_RGB
142 if (flags & OGL_FLAG_ALPHA)
144 if (ogl_intensity4_ok)
146 t->internalformat = GL_INTENSITY4;
147 t->format = GL_LUMINANCE;
149 else if (ogl_luminance4_alpha4_ok)
151 t->internalformat = GL_LUMINANCE4_ALPHA4;
152 t->format = GL_LUMINANCE_ALPHA;
154 else if (ogl_rgba2_ok)
156 t->internalformat = GL_RGBA2;
161 t->internalformat = ogl_rgba_internalformat;
167 // there are certainly smaller formats we could use here, but nothing needs it ATM.
168 t->internalformat = ogl_rgb_internalformat;
174 if (flags & OGL_FLAG_ALPHA)
176 t->internalformat = ogl_rgba_internalformat;
181 t->internalformat = ogl_rgb_internalformat;
185 t->wrapstate[0] = -1;
186 t->wrapstate[1] = -1;
189 ogl_init_texture_stats(t);
192 void ogl_reset_texture(ogl_texture* t)
194 ogl_init_texture(t, 0, 0, 0);
197 void ogl_reset_texture_stats_internal(void){
199 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
200 if (ogl_texture_list[i].handle>0){
201 ogl_init_texture_stats(&ogl_texture_list[i]);
204 void ogl_init_texture_list_internal(void){
206 ogl_texture_list_cur=0;
207 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
208 ogl_reset_texture(&ogl_texture_list[i]);
210 void ogl_smash_texture_list_internal(void){
213 memset(cross_lh,0,sizeof(cross_lh));
214 memset(primary_lh,0,sizeof(primary_lh));
215 memset(secondary_lh,0,sizeof(secondary_lh));
216 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
217 if (ogl_texture_list[i].handle>0){
218 glDeleteTextures( 1, &ogl_texture_list[i].handle );
219 ogl_texture_list[i].handle=0;
221 ogl_texture_list[i].wrapstate[0] = -1;
222 ogl_texture_list[i].wrapstate[1] = -1;
225 void ogl_vivify_texture_list_internal(void){
229 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
230 t=&ogl_texture_list[i];
231 if (t->w>0){//erk, realised this can't be done since we'd need the texture bm_data too. hmmm.
232 ogl_loadbmtexture(t);
237 ogl_texture* ogl_get_free_texture(void){
239 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
240 if (ogl_texture_list[ogl_texture_list_cur].handle<=0 && ogl_texture_list[ogl_texture_list_cur].w==0)
241 return &ogl_texture_list[ogl_texture_list_cur];
242 if (++ogl_texture_list_cur>=OGL_TEXTURE_LIST_SIZE)
243 ogl_texture_list_cur=0;
245 Error("OGL: texture list full!\n");
248 int ogl_texture_stats(void){
249 int used = 0, usedother = 0, usedidx = 0, usedrgb = 0, usedrgba = 0;
250 int databytes = 0, truebytes = 0, datatexel = 0, truetexel = 0, i;
251 int prio0=0,prio1=0,prio2=0,prio3=0,prioh=0;
254 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
255 t=&ogl_texture_list[i];
258 datatexel+=t->w*t->h;
259 truetexel+=t->tw*t->th;
260 databytes+=t->bytesu;
262 if (t->prio<0.299)prio0++;
263 else if (t->prio<0.399)prio1++;
264 else if (t->prio<0.499)prio2++;
265 else if (t->prio<0.599)prio3++;
267 if (t->format == GL_RGBA)
269 else if (t->format == GL_RGB)
271 else if (t->format == GL_COLOR_INDEX)
281 int idx, r, g, b, a, dbl, depth, res, colorsize, depthsize;
283 res = SWIDTH * SHEIGHT;
284 glGetIntegerv(GL_INDEX_BITS, &idx);
285 glGetIntegerv(GL_RED_BITS, &r);
286 glGetIntegerv(GL_GREEN_BITS, &g);
287 glGetIntegerv(GL_BLUE_BITS, &b);
288 glGetIntegerv(GL_ALPHA_BITS, &a);
289 glGetIntegerv(GL_DOUBLEBUFFER, &dbl);
291 glGetIntegerv(GL_DEPTH_BITS, &depth);
292 colorsize = (idx * res * dbl) / 8;
293 depthsize = res * depth / 8;
294 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);
295 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);
296 gr_printf(5, GAME_FONT->ft_h * 16 + 3 * 16, "total=%iK", (colorsize + depthsize + truebytes) / 1024);
298 // 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 int ogl_mem_target=-1;
302 void ogl_clean_texture_cache(void){
307 if (ogl_mem_target<0){
313 bytes=ogl_texture_stats();
314 while (bytes>ogl_mem_target){
315 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
316 t=&ogl_texture_list[i];
318 if (t->lastrend+f1_0*time<GameTime){
321 if (bytes<ogl_mem_target)
327 Error("not enough mem?");
332 void ogl_bindbmtex(grs_bitmap *bm){
333 if (bm->gltexture==NULL || bm->gltexture->handle<=0)
334 ogl_loadbmtexture(bm);
335 OGL_BINDTEXTURE(bm->gltexture->handle);
336 bm->gltexture->lastrend=GameTime;
337 bm->gltexture->numrend++;
338 //// if (bm->gltexture->numrend==80 || bm->gltexture->numrend==4000 || bm->gltexture->numrend==80000){
339 // if (bm->gltexture->numrend==100){
340 // bm->gltexture->prio+=0.1;
341 //// glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY,bm->gltexture->prio);
342 // glPrioritizeTextures(1,&bm->gltexture->handle,&bm->gltexture->prio);
345 //gltexture MUST be bound first
346 void ogl_texwrap(ogl_texture *gltexture,int state)
348 if (gltexture->wrapstate[active_texture_unit] != state || gltexture->numrend < 1)
350 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state);
351 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state);
352 gltexture->wrapstate[active_texture_unit] = state;
356 //crude texture precaching
357 //handles: powerups, walls, weapons, polymodels, etc.
358 //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.
359 //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 void ogl_cache_polymodel_textures(int model_num)
369 po = &Polygon_models[model_num];
370 for (i=0;i<po->n_textures;i++) {
371 // texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
372 ogl_loadbmtexture(&GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]);
375 void ogl_cache_vclip_textures(vclip *vc){
377 for (i=0;i<vc->num_frames;i++){
378 PIGGY_PAGE_IN(vc->frames[i]);
379 ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]);
383 void ogl_cache_vclipn_textures(int i)
385 if (i >= 0 && i < VCLIP_MAXNUM)
386 ogl_cache_vclip_textures(&Vclip[i]);
389 void ogl_cache_weapon_textures(int weapon_type)
395 w = &Weapon_info[weapon_type];
396 ogl_cache_vclipn_textures(w->flash_vclip);
397 ogl_cache_vclipn_textures(w->robot_hit_vclip);
398 ogl_cache_vclipn_textures(w->wall_hit_vclip);
399 if (w->render_type==WEAPON_RENDER_VCLIP)
400 ogl_cache_vclipn_textures(w->weapon_vclip);
401 else if (w->render_type == WEAPON_RENDER_POLYMODEL)
403 ogl_cache_polymodel_textures(w->model_num);
404 ogl_cache_polymodel_textures(w->model_num_inner);
408 void ogl_cache_level_textures(void)
417 ogl_reset_texture_stats_internal();//loading a new lev should reset textures
419 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
420 ogl_cache_vclipn_textures(Effects[i].dest_vclip);
421 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
423 if (ec->vc.num_frames>max_efx)
424 max_efx=ec->vc.num_frames;
426 glmprintf((0,"max_efx:%i\n",max_efx));
427 for (ef=0;ef<max_efx;ef++){
428 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
429 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
431 // if (ec->vc.num_frames>max_efx)
432 // max_efx=ec->vc.num_frames;
435 do_special_effects();
437 for (seg=0;seg<Num_segments;seg++){
438 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++){
439 sidep=&Segments[seg].sides[side];
440 tmap1=sidep->tmap_num;
441 tmap2=sidep->tmap_num2;
442 if (tmap1<0 || tmap1>=NumTextures){
443 glmprintf((0,"ogl_cache_level_textures %i %i %i %i\n",seg,side,tmap1,NumTextures));
447 PIGGY_PAGE_IN(Textures[tmap1]);
448 bm = &GameBitmaps[Textures[tmap1].index];
450 PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]);
451 bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index];
452 if (ogl_alttexmerge == 0 || (!OGL_SUPER_TRANSPARENT_OK && (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT)))
453 bm = texmerge_get_cached_bitmap( tmap1, tmap2 );
455 ogl_loadbmtexture(bm2);
457 // 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));
459 ogl_loadbmtexture(bm);
462 glmprintf((0,"finished ef:%i\n",ef));
464 reset_special_effects();
465 init_special_effects();
469 // always have lasers, concs, flares. Always shows player appearance, and at least concs are always available to disappear.
470 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
471 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
472 ogl_cache_weapon_textures(FLARE_ID);
473 ogl_cache_vclipn_textures(VCLIP_PLAYER_APPEARANCE);
474 ogl_cache_vclipn_textures(VCLIP_POWERUP_DISAPPEARANCE);
475 ogl_cache_polymodel_textures(Player_ship->model_num);
476 ogl_cache_vclipn_textures(Player_ship->expl_vclip_num);
478 for (i=0;i<Highest_object_index;i++){
479 if(Objects[i].render_type==RT_POWERUP){
480 ogl_cache_vclipn_textures(Objects[i].rtype.vclip_info.vclip_num);
481 switch (Objects[i].id){
483 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
487 case POW_VULCAN_WEAPON:
488 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]);
490 case POW_SPREADFIRE_WEAPON:
491 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]);
493 case POW_PLASMA_WEAPON:
494 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]);
496 case POW_FUSION_WEAPON:
497 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]);
499 /* case POW_MISSILE_1:
501 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
503 case POW_PROXIMITY_WEAPON:
504 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]);
506 case POW_HOMING_AMMO_1:
507 case POW_HOMING_AMMO_4:
508 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]);
510 case POW_SMARTBOMB_WEAPON:
511 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]);
513 case POW_MEGA_WEAPON:
514 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]);
518 else if(Objects[i].render_type==RT_POLYOBJ){
519 //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);
520 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp1_vclip_num);
521 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp2_vclip_num);
522 ogl_cache_weapon_textures(Robot_info[Objects[i].id].weapon_type);
523 ogl_cache_polymodel_textures(Objects[i].rtype.pobj_info.model_num);
527 glmprintf((0,"finished caching\n"));
528 r_cachedtexcount = r_texcount;
531 int r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc;
532 #define f2glf(x) (f2fl(x))
534 bool g3_draw_line(g3s_point *p0,g3s_point *p1)
537 c=grd_curcanv->cv_color;
538 OGL_DISABLE(TEXTURE_2D);
539 glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
541 glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));
542 glVertex3f(f2glf(p1->p3_vec.x),f2glf(p1->p3_vec.y),-f2glf(p1->p3_vec.z));
546 void ogl_drawcircle2(int nsides,int type,float xsc,float xo,float ysc,float yo){
550 for (i=0; i<nsides; i++) {
551 ang = 2.0*M_PI*i/nsides;
552 glVertex2f(cosf(ang)*xsc+xo,sinf(ang)*ysc+yo);
556 void ogl_drawcircle(int nsides,int type){
560 for (i=0; i<nsides; i++) {
561 ang = 2.0*M_PI*i/nsides;
562 glVertex2f(cosf(ang),sinf(ang));
566 int circle_list_init(int nsides,int type,int mode) {
567 int hand=glGenLists(1);
568 glNewList(hand, mode);
569 /* draw a unit radius circle in xy plane centered on origin */
570 ogl_drawcircle(nsides,type);
574 float bright_g[4]={ 32.0/256, 252.0/256, 32.0/256};
575 float dark_g[4]={ 32.0/256, 148.0/256, 32.0/256};
576 float darker_g[4]={ 32.0/256, 128.0/256, 32.0/256};
577 void ogl_draw_reticle(int cross,int primary,int secondary){
578 float scale=(float)Canvas_height/(float)grd_curscreen->sc_h;
580 // glTranslatef(0.5,0.5,0);
581 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);
582 glScalef(scale/320.0,scale/200.0,scale);//the positions are based upon the standard reticle at 320x200 res.
584 OGL_DISABLE(TEXTURE_2D);
586 if (!cross_lh[cross]){
587 cross_lh[cross]=glGenLists(1);
588 glNewList(cross_lh[cross], GL_COMPILE_AND_EXECUTE);
591 glColor3fv(darker_g);
592 glVertex2f(-4.0,4.0);
594 glColor3fv(bright_g);
597 glVertex2f(-2.0,2.0);
601 glVertex2f(-3.0,-2.0);
603 glColor3fv(bright_g);
604 glVertex2f(-2.0,-1.0);
607 glColor3fv(darker_g);
610 glColor3fv(bright_g);
617 glVertex2f(3.0,-2.0);
619 glColor3fv(bright_g);
620 glVertex2f(2.0,-1.0);
625 glCallList(cross_lh[cross]);
627 // if (Canvas_height>200)
628 // glLineWidth(Canvas_height/(float)200);
629 if (!primary_lh[primary]){
630 primary_lh[primary]=glGenLists(1);
631 glNewList(primary_lh[primary], GL_COMPILE_AND_EXECUTE);
636 glVertex2f(-14.0,-8.0);
637 glVertex2f(-8.0,-5.0);
639 glVertex2f(14.0,-8.0);
640 glVertex2f(8.0,-5.0);
645 glColor3fv(bright_g);
647 ogl_drawcircle2(6,GL_POLYGON,1.5,-7.0,1.5,-5.0);
649 ogl_drawcircle2(6,GL_POLYGON,1.5,7.0,1.5,-5.0);
653 glColor3fv(bright_g);
655 ogl_drawcircle2(4,GL_POLYGON,1.0,-14.0,1.0,-8.0);
657 ogl_drawcircle2(4,GL_POLYGON,1.0,14.0,1.0,-8.0);
661 glCallList(primary_lh[primary]);
662 // if (Canvas_height>200)
665 if (!secondary_lh[secondary]){
666 secondary_lh[secondary]=glGenLists(1);
667 glNewList(secondary_lh[secondary], GL_COMPILE_AND_EXECUTE);
671 glColor3fv(darker_g);
673 glColor3fv(bright_g);
674 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,-10.0,2.0,-1.0);
677 glColor3fv(darker_g);
679 glColor3fv(bright_g);
680 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,10.0,2.0,-1.0);
682 //bottom/middle secondary
684 glColor3fv(darker_g);
686 glColor3fv(bright_g);
687 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,0.0,2.0,-7.0);
691 glCallList(secondary_lh[secondary]);
695 int g3_draw_sphere(g3s_point *pnt,fix rad){
697 c=grd_curcanv->cv_color;
698 OGL_DISABLE(TEXTURE_2D);
699 // glPointSize(f2glf(rad));
700 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
701 // glBegin(GL_POINTS);
702 // glVertex3f(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
705 glTranslatef(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
706 glScalef(f2glf(rad),f2glf(rad),f2glf(rad));
707 if (!sphereh) sphereh=circle_list_init(20,GL_POLYGON,GL_COMPILE_AND_EXECUTE);
708 else glCallList(sphereh);
713 int gr_ucircle(fix xc1, fix yc1, fix r1)
716 c=grd_curcanv->cv_color;
717 OGL_DISABLE(TEXTURE_2D);
718 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
721 (f2fl(xc1) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width,
722 1.0 - (f2fl(yc1) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0);
723 glScalef(f2fl(r1) / last_width, f2fl(r1) / last_height, 1.0);
724 ogl_drawcircle(10 + 2 * (int)(M_PI * f2fl(r1) / 19), GL_LINE_LOOP);
728 int gr_circle(fix xc1,fix yc1,fix r1){
729 return gr_ucircle(xc1,yc1,r1);
732 bool g3_draw_poly(int nv,g3s_point **pointlist)
736 c=grd_curcanv->cv_color;
737 // 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);
738 OGL_DISABLE(TEXTURE_2D);
739 if (Gr_scanline_darkening_level >= GR_FADE_LEVELS)
740 glColor3f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c));
742 glColor4f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c), 1.0 - (float)Gr_scanline_darkening_level / ((float)GR_FADE_LEVELS - 1.0));
743 glBegin(GL_TRIANGLE_FAN);
745 // glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
746 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
752 void gr_upoly_tmap(int nverts, int *vert ){
753 mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
755 void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){
756 mprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called
758 extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist);
759 bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)
763 if (tmap_drawer_ptr==draw_tmap_flat){
764 /* fix average_light=0;
767 average_light += uvl_list[i].l;*/
768 OGL_DISABLE(TEXTURE_2D);
769 // glmprintf((0,"Gr_scanline_darkening_level=%i %f\n",Gr_scanline_darkening_level,Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
770 glColor4f(0,0,0,1.0-(Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
771 //glColor4f(0,0,0,f2fl(average_light/nv));
772 glBegin(GL_TRIANGLE_FAN);
774 // glColor4f(0,0,0,f2fl(uvl_list[c].l));
775 // glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
776 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
779 }else if (tmap_drawer_ptr==draw_tmap){
781 /* if (bm->bm_w !=64||bm->bm_h!=64)
782 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
783 OGL_ENABLE(TEXTURE_2D);
785 ogl_texwrap(bm->gltexture,GL_REPEAT);
786 glBegin(GL_TRIANGLE_FAN);
788 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
791 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
792 l=f2fl(uvl_list[c].l);
795 glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
796 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
797 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
801 mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
806 int active_texture_unit = 0;
808 void ogl_setActiveTexture(int t)
810 if (ogl_arb_multitexture_ok)
812 #ifdef GL_ARB_multitexture
814 glActiveTextureARB(GL_TEXTURE0_ARB);
816 glActiveTextureARB(GL_TEXTURE1_ARB);
819 else if (ogl_sgis_multitexture_ok)
821 #ifdef GL_SGIS_multitexture
823 glSelectTextureSGIS(GL_TEXTURE0_SGIS);
825 glSelectTextureSGIS(GL_TEXTURE1_SGIS);
828 active_texture_unit = t;
831 void ogl_MultiTexCoord2f(int t, float u, float v)
833 if (ogl_arb_multitexture_ok)
835 #ifdef GL_ARB_multitexture
837 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
839 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
842 else if (ogl_sgis_multitexture_ok)
844 #ifdef GL_SGIS_multitexture
846 glMultiTexCoord2fSGIS(GL_TEXTURE0_SGIS, u, v);
848 glMultiTexCoord2fSGIS(GL_TEXTURE1_SGIS, u, v);
853 bool g3_draw_tmap_2(int nv, g3s_point **pointlist, g3s_uvl *uvl_list, grs_bitmap *bmbot, grs_bitmap *bm, int orient)
855 #if ((defined(GL_NV_register_combiners) || defined(GL_NV_texture_env_combine4)) && (defined(GL_ARB_multitexture) || defined(GL_SGIS_multitexture)))
856 if ((/*ogl_nv_register_combiners_ok ||*/ ogl_nv_texture_env_combine4_ok) && (ogl_arb_multitexture_ok || ogl_sgis_multitexture_ok))
861 if (tmap_drawer_ptr != draw_tmap)
866 //ogl_setActiveTexture(0);
867 OGL_ENABLE(TEXTURE_2D);
868 ogl_bindbmtex(bmbot);
869 ogl_texwrap(bmbot->gltexture, GL_REPEAT);
870 // GL_MODULATE is fine for texture 0
872 ogl_setActiveTexture(1);
873 glEnable(GL_TEXTURE_2D);
875 ogl_texwrap(bm->gltexture,GL_REPEAT);
877 #ifdef GL_NV_register_combiners
878 if (ogl_nv_register_combiners_ok)
880 glEnable(GL_REGISTER_COMBINERS_NV);
881 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
882 // spare0 = tex0 * (1-alpha1) + tex1 * alpha1
883 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
884 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
885 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
886 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
888 GL_COMBINER0_NV, //GLenum stage
889 GL_RGB, //GLenum portion,
890 GL_DISCARD_NV, //GLenum abOutput,
891 GL_DISCARD_NV, //GLenum cdOutput,
892 GL_SPARE0_NV, //GLenum sumOutput,
893 GL_NONE, //GLenum scale,
894 GL_NONE, //GLenum bias,
895 GL_FALSE, //GLboolean abDotProduct,
896 GL_FALSE, //GLboolean cdDotProduct,
897 GL_FALSE //GLboolean muxSum
899 // out = spare0 * color
900 // ( out = AB + (1-A)C + D )
901 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
902 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
903 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
904 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
906 if (bm->bm_flags & BM_FLAG_SUPER_TRANSPARENT)
908 // out = alpha0*(1-tex1) + alpha1
909 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
910 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_BLUE);
911 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
912 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
916 // out = alpha0 + alpha1
917 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
918 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
919 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
920 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
923 GL_COMBINER0_NV, //GLenum stage
924 GL_ALPHA, //GLenum portion,
925 GL_DISCARD_NV, //GLenum abOutput,
926 GL_DISCARD_NV, //GLenum cdOutput,
927 GL_SPARE0_NV, //GLenum sumOutput,
928 GL_NONE, //GLenum scale,
929 GL_NONE, //GLenum bias,
930 GL_FALSE, //GLboolean abDotProduct,
931 GL_FALSE, //GLboolean cdDotProduct,
932 GL_FALSE //GLboolean muxSum
934 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
939 //http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_env_combine4.txt
940 //only GL_NV_texture_env_combine4 lets us do what we need:
941 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
943 //multiply top texture by color(vertex lighting) and add bottom texture(where alpha says to)
944 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
946 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
947 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
948 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE);
949 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_EXT);
951 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
952 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
953 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
954 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
956 //add up alpha channels
957 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
959 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
960 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
961 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PREVIOUS_EXT);
962 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
964 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
965 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
966 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
967 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
970 // GL_DECAL works sorta ok but the top texture is fullbright.
971 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
973 // GL_ARB_texture_env_combine comes close, but doesn't quite make it.
974 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
976 //// this gives effect like GL_DECAL:
977 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
978 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
979 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
980 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
983 // this properly shades the top texture, but the bottom texture doesn't get through.
984 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
985 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
986 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
990 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
991 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
992 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
994 glBegin(GL_TRIANGLE_FAN);
998 u1=1.0-f2glf(uvl_list[c].v);
999 v1=f2glf(uvl_list[c].u);
1002 u1=1.0-f2glf(uvl_list[c].u);
1003 v1=1.0-f2glf(uvl_list[c].v);
1006 u1=f2glf(uvl_list[c].v);
1007 v1=1.0-f2glf(uvl_list[c].u);
1010 u1=f2glf(uvl_list[c].u);
1011 v1=f2glf(uvl_list[c].v);
1014 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1017 l=f2fl(uvl_list[c].l);
1020 ogl_MultiTexCoord2f(0, f2glf(uvl_list[c].u), f2glf(uvl_list[c].v));
1021 ogl_MultiTexCoord2f(1, u1, v1);
1022 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1023 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1024 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1027 //ogl_setActiveTexture(1); // still the active texture
1028 #ifdef GL_NV_register_combiners
1029 if (ogl_nv_register_combiners_ok)
1031 glDisable(GL_REGISTER_COMBINERS_NV);
1036 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1038 glDisable(GL_TEXTURE_2D);
1039 ogl_setActiveTexture(0);
1047 g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
1050 /* if (bm->bm_w !=64||bm->bm_h!=64)
1051 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
1052 OGL_ENABLE(TEXTURE_2D);
1054 ogl_texwrap(bm->gltexture,GL_REPEAT);
1055 glBegin(GL_TRIANGLE_FAN);
1059 u1=1.0-f2glf(uvl_list[c].v);
1060 v1=f2glf(uvl_list[c].u);
1063 u1=1.0-f2glf(uvl_list[c].u);
1064 v1=1.0-f2glf(uvl_list[c].v);
1067 u1=f2glf(uvl_list[c].v);
1068 v1=1.0-f2glf(uvl_list[c].u);
1071 u1=f2glf(uvl_list[c].u);
1072 v1=f2glf(uvl_list[c].v);
1075 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1078 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
1079 l=f2fl(uvl_list[c].l);
1082 glTexCoord2f(u1,v1);
1083 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1084 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1085 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1092 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
1095 vms_vector pv,v1;//,v2;
1099 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1100 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1102 OGL_ENABLE(TEXTURE_2D);
1104 ogl_texwrap(bm->gltexture,GL_CLAMP);
1107 glColor3f(1.0,1.0,1.0);
1108 width = fixmul(width,Matrix_scale.x);
1109 height = fixmul(height,Matrix_scale.y);
1111 // g3_rotate_point(&p[i],pos);
1112 vm_vec_sub(&v1,pos,&View_position);
1113 vm_vec_rotate(&pv,&v1,&View_matrix);
1114 // printf(" %f,%f,%f->",f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1117 glTexCoord2f(0.0, 0.0);
1122 glTexCoord2f(bm->gltexture->u, 0.0);
1127 glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
1132 glTexCoord2f(0.0, bm->gltexture->v);
1137 // vm_vec_rotate(&v2,&v1,&View_matrix);
1138 // vm_vec_sub(&v1,&v2,&pv);
1139 //vm_vec_sub(&v1,&pv,&v2);
1140 // vm_vec_sub(&v2,&pv,&v1);
1141 glVertex3f(f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1142 // printf("%f,%f,%f ",f2glf(v1.x),f2glf(v1.y),-f2glf(v1.z));
1150 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
1152 GLfloat xo,yo,xf,yf;
1153 GLfloat u1,u2,v1,v2;
1155 x+=grd_curcanv->cv_bitmap.bm_x;
1156 y+=grd_curcanv->cv_bitmap.bm_y;
1157 xo=x/(float)last_width;
1158 xf=(bm->bm_w+x)/(float)last_width;
1159 yo=1.0-y/(float)last_height;
1160 yf=1.0-(bm->bm_h+y)/(float)last_height;
1162 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1163 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1165 /* glEnABLE(ALPHA_TEST);
1166 glAlphaFunc(GL_GREATER,0.0);*/
1168 OGL_ENABLE(TEXTURE_2D);
1170 ogl_texwrap(bm->gltexture,GL_CLAMP);
1174 if (bm->bm_w==bm->gltexture->w)
1175 u2=bm->gltexture->u;
1177 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1179 u1=bm->bm_x/(float)bm->gltexture->tw;
1180 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1184 if (bm->bm_h==bm->gltexture->h)
1185 v2=bm->gltexture->v;
1187 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1189 v1=bm->bm_y/(float)bm->gltexture->th;
1190 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1195 glColor3f(1.0,1.0,1.0);
1197 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
1198 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1199 glTexCoord2f(u2, v1); glVertex2f(xf, yo);
1200 glTexCoord2f(u2, v2); glVertex2f(xf, yf);
1201 glTexCoord2f(u1, v2); glVertex2f(xo, yf);
1203 // glDisABLE(ALPHA_TEST);
1207 bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){
1208 return ogl_ubitmapm_c(x,y,bm,-1);
1209 // return ogl_ubitblt(bm->bm_w,bm->bm_h,x,y,0,0,bm,NULL);
1212 //also upsidedown, currently.
1213 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1215 GLfloat xo,yo;//,xs,ys;
1216 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));
1221 xo=dx/(float)last_width;
1222 // xo=dx/(float)grd_curscreen->sc_w;
1223 // xs=w/(float)last_width;
1224 //yo=1.0-dy/(float)last_height;
1225 yo=1.0-(dy+h)/(float)last_height;
1226 // ys=h/(float)last_height;
1228 // OGL_ENABLE(TEXTURE_2D);
1230 OGL_DISABLE(TEXTURE_2D);
1231 glRasterPos2f(xo,yo);
1232 ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h,GL_RGBA);
1233 glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);
1239 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)
1241 GLfloat xo,yo,xs,ys;
1242 GLfloat u1,v1;//,u2,v2;
1244 // unsigned char *oldpal;
1247 ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA);
1249 tex.lw=src->bm_rowsize;
1251 /* if (w==src->bm_w && sx==0){
1254 u1=sx/(float)src->bm_w*src->glu;
1255 u2=w/(float)src->bm_w*src->glu+u1;
1257 if (h==src->bm_h && sy==0){
1260 v1=sy/(float)src->bm_h*src->glv;
1261 v2=h/(float)src->bm_h*src->glv+v1;
1267 xo=dx/(float)last_width;
1268 xs=dw/(float)last_width;
1269 yo=1.0-dy/(float)last_height;
1270 ys=dh/(float)last_height;
1272 OGL_ENABLE(TEXTURE_2D);
1275 ogl_pal=gr_current_pal;
1276 ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags);
1279 OGL_BINDTEXTURE(tex.handle);
1281 ogl_texwrap(&tex,GL_CLAMP);
1284 glColor3f(1.0,1.0,1.0);
1285 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1286 glTexCoord2f(tex.u, v1); glVertex2f(xo+xs, yo);
1287 glTexCoord2f(tex.u, tex.v); glVertex2f(xo+xs, yo-ys);
1288 glTexCoord2f(u1, tex.v); glVertex2f(xo, yo-ys);
1290 ogl_freetexture(&tex);
1293 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1294 return ogl_ubitblt_i(w,h,dx,dy,w,h,sx,sy,src,dest);
1297 bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1299 unsigned char *d,*s;
1303 w1=grd_curscreen->sc_w;h1=grd_curscreen->sc_h;
1304 if (w1*h1*3>OGLTEXBUFSIZE)
1305 Error("ogl_ubitblt_tolinear: screen res larger than OGLTEXBUFSIZE\n");
1307 if (ogl_readpixels_ok>0){
1308 OGL_DISABLE(TEXTURE_2D);
1309 glReadBuffer(GL_FRONT);
1310 glReadPixels(0,0,w1,h1,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1311 // glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1312 // glReadPixels(sx,sy,w+sx,h+sy,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1314 memset(texbuf,0,w1*h1*3);
1318 d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1319 s=texbuf+((h1-(i+sy+1))*w1+sx)*3;
1321 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1328 unsigned char *d,*s,*e;
1329 if (w*h*3>OGLTEXBUFSIZE)
1330 Error("ogl_ubitblt_tolinear: size larger than OGLTEXBUFSIZE\n");
1333 #if 1//also seems to cause a mess. need to look into it a bit more..
1334 if (ogl_readpixels_ok>0){
1335 OGL_DISABLE(TEXTURE_2D);
1336 glReadBuffer(GL_FRONT);
1337 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1338 glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1341 memset(texbuf,0,w*h*3);
1342 // d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1343 d=dest->bm_data+dx+dy*dest->bm_rowsize;
1345 s=texbuf+w*(h-(i+1))*3;
1347 if (s<texbuf){Error("blah1\n");}
1348 if (d<dest->bm_data){Error("blah3\n");}
1349 // d=dest->bm_data+(i*dest->bm_rowsize);
1353 if (s>texbuf+w*h*3-3){Error("blah2\n");}
1354 if (d>dest->bm_data+dest->bm_rowsize*(h+dy)+dx ){Error("blah4\n");}
1355 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1361 d+=dest->bm_rowsize;
1363 glmprintf((0,"c=%i w*h=%i\n",c,w*h));
1368 bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1369 #if 0 //just seems to cause a mess.
1370 GLfloat xo,yo;//,xs,ys;
1375 // xo=dx/(float)last_width;
1376 xo=dx/(float)grd_curscreen->sc_w;
1377 // yo=1.0-(dy+h)/(float)last_height;
1378 yo=1.0-(dy+h)/(float)grd_curscreen->sc_h;
1381 OGL_DISABLE(TEXTURE_2D);
1382 glReadBuffer(GL_FRONT);
1383 glRasterPos2f(xo,yo);
1384 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1385 glCopyPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_COLOR);
1391 grs_canvas *offscreen_save_canv = NULL, *offscreen_canv = NULL;
1393 void ogl_start_offscreen_render(int x, int y, int w, int h)
1396 Error("ogl_start_offscreen_render: offscreen_canv!=NULL");
1397 offscreen_save_canv = grd_curcanv;
1398 offscreen_canv = gr_create_sub_canvas(grd_curcanv, x, y, w, h);
1399 gr_set_current_canvas(offscreen_canv);
1400 glDrawBuffer(GL_BACK);
1402 void ogl_end_offscreen_render(void)
1406 if (!offscreen_canv)
1407 Error("ogl_end_offscreen_render: no offscreen_canv");
1409 glDrawBuffer(GL_FRONT);
1410 glReadBuffer(GL_BACK);
1411 OGL_DISABLE(TEXTURE_2D);
1413 y = last_height - offscreen_canv->cv_bitmap.bm_y - offscreen_canv->cv_bitmap.bm_h;
1414 glRasterPos2f(offscreen_canv->cv_bitmap.bm_x/(float)last_width, y/(float)last_height);
1415 glCopyPixels(offscreen_canv->cv_bitmap.bm_x, y,
1416 offscreen_canv->cv_bitmap.bm_w,
1417 offscreen_canv->cv_bitmap.bm_h, GL_COLOR);
1419 gr_free_sub_canvas(offscreen_canv);
1420 gr_set_current_canvas(offscreen_save_canv);
1421 offscreen_canv=NULL;
1424 void ogl_start_frame(void){
1425 r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;
1426 // gl_badtexture=500;
1428 OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);
1429 glClearColor(0.0, 0.0, 0.0, 0.0);
1430 // glEnable(GL_ALPHA_TEST);
1431 // glAlphaFunc(GL_GREATER,0.01);
1432 glShadeModel(GL_SMOOTH);
1433 glMatrixMode(GL_PROJECTION);
1434 glLoadIdentity();//clear matrix
1435 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1436 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),0.01,1000000.0);
1437 gluPerspective(90.0,1.0,0.01,1000000.0);
1438 //gluPerspective(90.0,(GLfloat)(Canvas_width*3)/(GLfloat)(Canvas_height*4),0.01,1000000.0);
1439 // gluPerspective(75.0,(GLfloat)Canvas_width/(GLfloat)Canvas_height,1.0,1000000.0);
1440 glMatrixMode(GL_MODELVIEW);
1441 glLoadIdentity();//clear matrix
1443 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1444 // glDisABLE(DITHER);
1445 // glScalef(1.0,1.0,-1.0);
1446 // glScalef(1.0,1.0,-1.0);
1449 // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1450 // OGL_TEXENV(GL_TEXTURE_ENV_MODE,GL_MODULATE);
1451 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1452 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1453 // OGL_TEXPARAM(GL_TEXTURE_MAG_FILTER,GL_texmagfilt);
1454 // OGL_TEXPARAM(GL_TEXTURE_MIN_FILTER,GL_texminfilt);
1455 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1456 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1459 void merge_textures_stats(void);
1461 void ogl_end_frame(void){
1462 // OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);
1463 OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1465 // merge_textures_stats();
1466 // ogl_texture_stats();
1468 // glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1469 glMatrixMode(GL_PROJECTION);
1470 glLoadIdentity();//clear matrix
1471 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
1472 glMatrixMode(GL_MODELVIEW);
1473 glLoadIdentity();//clear matrix
1474 // glDisABLE(BLEND);
1475 //glDisABLE(ALPHA_TEST);
1476 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1477 // ogl_swap_buffers();//platform specific code
1478 // glClear(GL_COLOR_BUFFER_BIT);
1480 void ogl_swap_buffers(void){
1481 ogl_clean_texture_cache();
1482 if (gr_renderstats){
1483 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);
1484 // 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 ogl_swap_buffers_internal();
1488 glClear(GL_COLOR_BUFFER_BIT);
1491 void ogl_init_shared_palette(void)
1493 #ifdef GL_EXT_paletted_texture
1494 if (ogl_shared_palette_ok)
1498 glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1499 //glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, ogl_pal);
1501 for (i = 0; i < 256; i++)
1505 texbuf[i * 4] = 255;
1506 texbuf[i * 4 + 1] = 255;
1507 texbuf[i * 4 + 2] = 255;
1508 texbuf[i * 4 + 3] = 0;
1513 texbuf[i * 4 + 1] = 0;
1514 texbuf[i * 4 + 2] = 0;
1515 texbuf[i * 4 + 3] = 0;
1519 texbuf[i * 4] = gr_current_pal[i * 3] * 4;
1520 texbuf[i * 4 + 1] = gr_current_pal[i * 3 + 1] * 4;
1521 texbuf[i * 4 + 2] = gr_current_pal[i * 3 + 2] * 4;
1522 texbuf[i * 4 + 3] = 255;
1525 glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
1530 int tex_format_supported(int iformat,int format){
1533 if (!ogl_intensity4_ok) return 0; break;
1534 case GL_LUMINANCE4_ALPHA4:
1535 if (!ogl_luminance4_alpha4_ok) return 0; break;
1537 if (!ogl_rgba2_ok) return 0; break;
1539 if (ogl_gettexlevelparam_ok){
1540 GLint internalFormat;
1541 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, iformat, 64, 64, 0,
1542 format, GL_UNSIGNED_BYTE, texbuf);//NULL?
1543 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
1544 GL_TEXTURE_INTERNAL_FORMAT,
1546 return (internalFormat==iformat);
1551 //little hack to find the largest or equal multiple of 2 for a given number
1554 for (i=2;i<=4096;i*=2)
1559 //GLubyte texbuf[512*512*4];
1560 GLubyte texbuf[OGLTEXBUFSIZE];
1561 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)
1563 // GLushort *tex=(GLushort *)texp;
1565 if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
1566 Error("texture toobig %i %i",twidth,theight);
1569 for (y=0;y<theight;y++){
1570 i=dxo+truewidth*(y+dyo);
1571 for (x=0;x<twidth;x++){
1572 if (x<width && y<height)
1575 c = 256; // fill the pad space with transparency (or blackness)
1576 if (c == 254 && (bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1580 case GL_LUMINANCE_ALPHA:
1588 (*(texp++)) = 0; // transparent pixel
1590 case GL_COLOR_INDEX:
1594 Error("ogl_filltexbuf unhandled super-transparent texformat\n");
1598 else if ((c == 255 && (bm_flags & BM_FLAG_TRANSPARENT)) || c == 256)
1604 case GL_LUMINANCE_ALPHA:
1617 (*(texp++))=0;//transparent pixel
1619 case GL_COLOR_INDEX:
1623 Error("ogl_filltexbuf unknown texformat\n");
1628 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. :)
1631 case GL_LUMINANCE_ALPHA:
1636 (*(texp++)) = ogl_pal[c * 3] * 4;
1637 (*(texp++)) = ogl_pal[c * 3 + 1] * 4;
1638 (*(texp++)) = ogl_pal[c * 3 + 2] * 4;
1641 //(*(texp++))=gr_palette[c*3]*4;
1642 //(*(texp++))=gr_palette[c*3+1]*4;
1643 //(*(texp++))=gr_palette[c*3+2]*4;
1644 (*(texp++))=ogl_pal[c*3]*4;
1645 (*(texp++))=ogl_pal[c*3+1]*4;
1646 (*(texp++))=ogl_pal[c*3+2]*4;
1647 (*(texp++))=255;//not transparent
1648 // (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
1650 case GL_COLOR_INDEX:
1654 Error("ogl_filltexbuf unknown texformat\n");
1661 int tex_format_verify(ogl_texture *tex){
1662 while (!tex_format_supported(tex->internalformat,tex->format)){
1663 glmprintf((0,"tex format %x not supported",tex->internalformat));
1664 switch (tex->internalformat){
1666 if (ogl_luminance4_alpha4_ok){
1667 tex->internalformat=GL_LUMINANCE4_ALPHA4;
1668 tex->format=GL_LUMINANCE_ALPHA;
1670 }//note how it will fall through here if the statement is false
1671 case GL_LUMINANCE4_ALPHA4:
1673 tex->internalformat=GL_RGBA2;
1674 tex->format=GL_RGBA;
1676 }//note how it will fall through here if the statement is false
1678 tex->internalformat = ogl_rgba_internalformat;
1679 tex->format=GL_RGBA;
1682 mprintf((0,"...no tex format to fall back on\n"));
1685 glmprintf((0,"...falling back to %x\n",tex->internalformat));
1689 void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){
1691 if (tex->tw!=w || tex->th!=h){
1692 u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h);
1693 glmprintf((0,"shrunken texture?\n"));
1696 if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
1697 tex->bytes=((float)w*h*dbits)/8.0;
1698 tex->bytesu=((float)u*dbits)/8.0;
1700 tex->bytes=((float)w*h*bits)/8.0;
1701 tex->bytesu=((float)u*bits)/8.0;
1703 glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes));
1705 void tex_set_size(ogl_texture *tex){
1708 if (ogl_gettexlevelparam_ok){
1710 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w);
1711 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h);
1712 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t;
1713 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t;
1714 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t;
1715 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t;
1716 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t;
1717 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t;
1718 #ifdef GL_EXT_paletted_texture
1719 if (ogl_paletted_texture_ok)
1721 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INDEX_SIZE_EXT, &t);
1729 switch (tex->format){
1733 case GL_LUMINANCE_ALPHA:
1740 case GL_COLOR_INDEX:
1744 Error("tex_set_size unknown texformat\n");
1747 tex_set_size1(tex,bi,a,w,h);
1749 //loads a palettized bitmap into a ogl RGBA texture.
1750 //Sizes and pads dimensions to multiples of 2 if necessary.
1751 //In theory this could be a problem for repeating textures, but all real
1752 //textures (not sprites, etc) in descent are 64x64, so we are ok.
1753 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
1754 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags)
1756 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
1757 // int internalformat=GL_RGBA;
1758 // int format=GL_RGBA;
1760 tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
1761 // tex->tw=tex->w;tex->th=tex->h;//feeling lucky?
1763 if(gr_badtexture>0) return;
1765 #if !(defined(__APPLE__) && defined(__MACH__))
1766 // always fails on OS X, but textures work fine!
1767 if (tex_format_verify(tex))
1771 //calculate u/v values that would make the resulting texture correctly sized
1772 tex->u=(float)tex->w/(float)tex->tw;
1773 tex->v=(float)tex->h/(float)tex->th;
1775 #ifdef GL_EXT_paletted_texture
1776 if (ogl_shared_palette_ok && (tex->format == GL_RGBA || tex->format == GL_RGB) &&
1777 !(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.
1780 // descent makes palette entries 254 and 255 both do double duty, depending upon the setting of BM_FLAG_SUPER_TRANSPARENT and BM_FLAG_TRANSPARENT.
1781 // 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.)
1782 // We don't handle super transparent textures with ogl yet, so we don't bother checking that here.
1783 int usesthetransparentindexcolor = 0, usesthesupertransparentindexcolor = 0;
1785 if (!(bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1789 for (i = 0; i < tex->w * tex->h; ++i)
1791 usesthesupertransparentindexcolor += 1;
1793 if (!(bm_flags & BM_FLAG_TRANSPARENT))
1797 for (i=0; i < tex->w * tex->h; ++i)
1799 usesthetransparentindexcolor += 1;
1801 if (!usesthetransparentindexcolor && !usesthesupertransparentindexcolor)
1803 tex->internalformat = GL_COLOR_INDEX8_EXT;
1804 tex->format = GL_COLOR_INDEX;
1807 // printf("bm data=%p w=%i h=%i transparent:%i supertrans:%i\n", data, tex->w, tex->h, usesthetransparentindexcolor, usesthesupertransparentindexcolor);
1811 // if (width!=twidth || height!=theight)
1812 // glmprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
1813 ogl_filltexbuf(data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags);
1815 // Generate OpenGL texture IDs.
1816 glGenTextures(1, &tex->handle);
1819 glPrioritizeTextures(1,&tex->handle,&tex->prio);
1821 // Give our data to OpenGL.
1823 OGL_BINDTEXTURE(tex->handle);
1825 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1827 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1828 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1829 if (ogl_ext_texture_filter_anisotropic_ok && GL_texanisofilt)
1830 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_texanisofilt);
1834 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1835 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1837 // domipmap=0;//mipmaps aren't used in GL_NEAREST anyway, and making the mipmaps is pretty slow
1838 //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.
1840 if (tex->wantmip && GL_needmipmaps)
1841 gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
1842 tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
1844 glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
1845 tex->tw, tex->th, 0, tex->format, // RGBA textures.
1846 GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
1852 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));
1856 unsigned char decodebuf[512*512];
1858 void ogl_loadbmtexture_f(grs_bitmap *bm, int flags)
1861 while (bm->bm_parent)
1864 if (bm->gltexture==NULL){
1865 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));
1868 if (bm->gltexture->handle>0)
1870 if (bm->gltexture->w==0){
1871 bm->gltexture->lw=bm->bm_w;
1872 bm->gltexture->w=bm->bm_w;
1873 bm->gltexture->h=bm->bm_h;
1876 if (bm->bm_flags & BM_FLAG_RLE){
1877 unsigned char * dbits;
1878 unsigned char * sbits;
1882 if (bm->bm_flags & BM_FLAG_RLE_BIG)
1885 sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)];
1888 for (i=0; i < bm->bm_h; i++ ) {
1889 gr_rle_decode(sbits,dbits);
1890 if ( bm->bm_flags & BM_FLAG_RLE_BIG )
1891 sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)])));
1893 sbits += (int)bm->bm_data[4+i];
1898 ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags);
1901 void ogl_loadbmtexture(grs_bitmap *bm)
1903 ogl_loadbmtexture_f(bm, OGL_FLAG_MIPMAP);
1906 void ogl_freetexture(ogl_texture *gltexture)
1908 if (gltexture->handle>0) {
1910 glmprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
1911 glDeleteTextures( 1, &gltexture->handle );
1912 // gltexture->handle=0;
1913 ogl_reset_texture(gltexture);
1916 void ogl_freebmtexture(grs_bitmap *bm){
1918 ogl_freetexture(bm->gltexture);
1921 // glmprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
1922 // glDeleteTextures( 1, &bm->gltexture );
1923 // bm->gltexture=-1;