1 /* $Id: ogl.c,v 1.30 2004-05-22 22:24:24 btb Exp $ */
4 * Graphics support functions for OpenGL.
19 #if defined(__APPLE__) && defined(__MACH__)
20 #include <OpenGL/gl.h>
21 #include <OpenGL/glu.h>
32 #include "../../3d/globvars.h"
52 //change to 1 for lots of spew.
54 #define glmprintf(a) mprintf(a)
63 #if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__)
64 #define cosf(a) cos(a)
65 #define sinf(a) sin(a)
68 unsigned char *ogl_pal=gr_palette;
70 int GL_texmagfilt=GL_NEAREST;
71 int GL_texminfilt=GL_NEAREST;
72 float GL_texanisofilt = 0;
75 int last_width=-1,last_height=-1;
76 int GL_TEXTURE_2D_enabled=-1;
77 int GL_texclamp_enabled=-1;
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;
87 int ogl_readpixels_ok=1;
88 int ogl_gettexlevelparam_ok=1;
89 #ifdef GL_ARB_multitexture
90 int ogl_arb_multitexture_ok=0;
92 #ifdef GL_SGIS_multitexture
93 int ogl_sgis_multitexture_ok=0;
95 int ogl_nv_texture_env_combine4_ok = 0;
96 #ifdef GL_NV_register_combiners
97 int ogl_nv_register_combiners_ok = 0;
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;
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};
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);
117 ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE];
118 int ogl_texture_list_cur;
120 /* some function prototypes */
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);
133 void ogl_init_texture_stats(ogl_texture* t){
134 t->prio=0.3;//default prio
138 void ogl_init_texture(ogl_texture* t, int w, int h, int flags)
141 if (flags & OGL_FLAG_NOCOLOR)
143 // use GL_INTENSITY instead of GL_RGB
144 if (flags & OGL_FLAG_ALPHA)
146 if (ogl_intensity4_ok)
148 t->internalformat = GL_INTENSITY4;
149 t->format = GL_LUMINANCE;
151 else if (ogl_luminance4_alpha4_ok)
153 t->internalformat = GL_LUMINANCE4_ALPHA4;
154 t->format = GL_LUMINANCE_ALPHA;
156 else if (ogl_rgba2_ok)
158 t->internalformat = GL_RGBA2;
163 t->internalformat = ogl_rgba_internalformat;
169 // there are certainly smaller formats we could use here, but nothing needs it ATM.
170 t->internalformat = ogl_rgb_internalformat;
176 if (flags & OGL_FLAG_ALPHA)
178 t->internalformat = ogl_rgba_internalformat;
183 t->internalformat = ogl_rgb_internalformat;
187 t->wrapstate[0] = -1;
188 t->wrapstate[1] = -1;
191 ogl_init_texture_stats(t);
194 void ogl_reset_texture(ogl_texture* t)
196 ogl_init_texture(t, 0, 0, 0);
199 void ogl_reset_texture_stats_internal(void){
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]);
206 void ogl_init_texture_list_internal(void){
208 ogl_texture_list_cur=0;
209 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
210 ogl_reset_texture(&ogl_texture_list[i]);
212 void ogl_smash_texture_list_internal(void){
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;
223 ogl_texture_list[i].wrapstate[0] = -1;
224 ogl_texture_list[i].wrapstate[1] = -1;
227 void ogl_vivify_texture_list_internal(void){
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);
239 ogl_texture* ogl_get_free_texture(void){
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;
247 Error("OGL: texture list full!\n");
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;
256 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
257 t=&ogl_texture_list[i];
260 datatexel+=t->w*t->h;
261 truetexel+=t->tw*t->th;
262 databytes+=t->bytesu;
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++;
269 if (t->format == GL_RGBA)
271 else if (t->format == GL_RGB)
273 else if (t->format == GL_COLOR_INDEX)
283 int idx, r, g, b, a, dbl, depth, res, colorsize, depthsize;
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);
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);
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));
303 int ogl_mem_target=-1;
304 void ogl_clean_texture_cache(void){
309 if (ogl_mem_target<0){
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];
320 if (t->lastrend+f1_0*time<GameTime){
323 if (bytes<ogl_mem_target)
329 Error("not enough mem?");
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);
347 //gltexture MUST be bound first
348 void ogl_texwrap(ogl_texture *gltexture,int state)
350 if (gltexture->wrapstate[active_texture_unit] != state || gltexture->numrend < 1)
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;
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
364 void ogl_cache_polymodel_textures(int model_num)
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]);
377 void ogl_cache_vclip_textures(vclip *vc){
379 for (i=0;i<vc->num_frames;i++){
380 PIGGY_PAGE_IN(vc->frames[i]);
381 ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]);
385 void ogl_cache_vclipn_textures(int i)
387 if (i >= 0 && i < VCLIP_MAXNUM)
388 ogl_cache_vclip_textures(&Vclip[i]);
391 void ogl_cache_weapon_textures(int weapon_type)
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)
405 ogl_cache_polymodel_textures(w->model_num);
406 ogl_cache_polymodel_textures(w->model_num_inner);
410 void ogl_cache_level_textures(void)
419 ogl_reset_texture_stats_internal();//loading a new lev should reset textures
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) )
425 if (ec->vc.num_frames>max_efx)
426 max_efx=ec->vc.num_frames;
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) )
433 // if (ec->vc.num_frames>max_efx)
434 // max_efx=ec->vc.num_frames;
437 do_special_effects();
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));
449 PIGGY_PAGE_IN(Textures[tmap1]);
450 bm = &GameBitmaps[Textures[tmap1].index];
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 );
457 ogl_loadbmtexture(bm2);
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));
461 ogl_loadbmtexture(bm);
464 glmprintf((0,"finished ef:%i\n",ef));
466 reset_special_effects();
467 init_special_effects();
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);
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){
485 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
489 case POW_VULCAN_WEAPON:
490 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]);
492 case POW_SPREADFIRE_WEAPON:
493 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]);
495 case POW_PLASMA_WEAPON:
496 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]);
498 case POW_FUSION_WEAPON:
499 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]);
501 /* case POW_MISSILE_1:
503 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
505 case POW_PROXIMITY_WEAPON:
506 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]);
508 case POW_HOMING_AMMO_1:
509 case POW_HOMING_AMMO_4:
510 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]);
512 case POW_SMARTBOMB_WEAPON:
513 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]);
515 case POW_MEGA_WEAPON:
516 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]);
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);
529 glmprintf((0,"finished caching\n"));
530 r_cachedtexcount = r_texcount;
533 int r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc;
534 #define f2glf(x) (f2fl(x))
536 bool g3_draw_line(g3s_point *p0,g3s_point *p1)
539 c=grd_curcanv->cv_color;
540 OGL_DISABLE(TEXTURE_2D);
541 glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
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));
548 void ogl_drawcircle2(int nsides,int type,float xsc,float xo,float ysc,float yo){
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);
558 void ogl_drawcircle(int nsides,int type){
562 for (i=0; i<nsides; i++) {
563 ang = 2.0*M_PI*i/nsides;
564 glVertex2f(cosf(ang),sinf(ang));
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);
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;
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.
586 OGL_DISABLE(TEXTURE_2D);
588 if (!cross_lh[cross]){
589 cross_lh[cross]=glGenLists(1);
590 glNewList(cross_lh[cross], GL_COMPILE_AND_EXECUTE);
593 glColor3fv(darker_g);
594 glVertex2f(-4.0,4.0);
596 glColor3fv(bright_g);
599 glVertex2f(-2.0,2.0);
603 glVertex2f(-3.0,-2.0);
605 glColor3fv(bright_g);
606 glVertex2f(-2.0,-1.0);
609 glColor3fv(darker_g);
612 glColor3fv(bright_g);
619 glVertex2f(3.0,-2.0);
621 glColor3fv(bright_g);
622 glVertex2f(2.0,-1.0);
627 glCallList(cross_lh[cross]);
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);
638 glVertex2f(-14.0,-8.0);
639 glVertex2f(-8.0,-5.0);
641 glVertex2f(14.0,-8.0);
642 glVertex2f(8.0,-5.0);
647 glColor3fv(bright_g);
649 ogl_drawcircle2(6,GL_POLYGON,1.5,-7.0,1.5,-5.0);
651 ogl_drawcircle2(6,GL_POLYGON,1.5,7.0,1.5,-5.0);
655 glColor3fv(bright_g);
657 ogl_drawcircle2(4,GL_POLYGON,1.0,-14.0,1.0,-8.0);
659 ogl_drawcircle2(4,GL_POLYGON,1.0,14.0,1.0,-8.0);
663 glCallList(primary_lh[primary]);
664 // if (Canvas_height>200)
667 if (!secondary_lh[secondary]){
668 secondary_lh[secondary]=glGenLists(1);
669 glNewList(secondary_lh[secondary], GL_COMPILE_AND_EXECUTE);
673 glColor3fv(darker_g);
675 glColor3fv(bright_g);
676 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,-10.0,2.0,-1.0);
679 glColor3fv(darker_g);
681 glColor3fv(bright_g);
682 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,10.0,2.0,-1.0);
684 //bottom/middle secondary
686 glColor3fv(darker_g);
688 glColor3fv(bright_g);
689 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,0.0,2.0,-7.0);
693 glCallList(secondary_lh[secondary]);
697 int g3_draw_sphere(g3s_point *pnt,fix rad){
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));
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);
715 int gr_ucircle(fix xc1, fix yc1, fix r1)
718 c=grd_curcanv->cv_color;
719 OGL_DISABLE(TEXTURE_2D);
720 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
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);
730 int gr_circle(fix xc1,fix yc1,fix r1){
731 return gr_ucircle(xc1,yc1,r1);
734 bool g3_draw_poly(int nv,g3s_point **pointlist)
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));
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);
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));
754 void gr_upoly_tmap(int nverts, int *vert ){
755 mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
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
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)
765 if (tmap_drawer_ptr==draw_tmap_flat){
766 /* fix average_light=0;
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);
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));
781 }else if (tmap_drawer_ptr==draw_tmap){
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);
787 ogl_texwrap(bm->gltexture,GL_REPEAT);
788 glBegin(GL_TRIANGLE_FAN);
790 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
793 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
794 l=f2fl(uvl_list[c].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));
803 mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
808 int active_texture_unit = 0;
810 void ogl_setActiveTexture(int t)
812 if (ogl_arb_multitexture_ok)
814 #ifdef GL_ARB_multitexture
816 glActiveTextureARB(GL_TEXTURE0_ARB);
818 glActiveTextureARB(GL_TEXTURE1_ARB);
821 else if (ogl_sgis_multitexture_ok)
823 #ifdef GL_SGIS_multitexture
825 glSelectTextureSGIS(GL_TEXTURE0_SGIS);
827 glSelectTextureSGIS(GL_TEXTURE1_SGIS);
830 active_texture_unit = t;
833 void ogl_MultiTexCoord2f(int t, float u, float v)
835 if (ogl_arb_multitexture_ok)
837 #ifdef GL_ARB_multitexture
839 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
841 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
844 else if (ogl_sgis_multitexture_ok)
846 #ifdef GL_SGIS_multitexture
848 glMultiTexCoord2fSGIS(GL_TEXTURE0_SGIS, u, v);
850 glMultiTexCoord2fSGIS(GL_TEXTURE1_SGIS, u, v);
855 bool g3_draw_tmap_2(int nv, g3s_point **pointlist, g3s_uvl *uvl_list, grs_bitmap *bmbot, grs_bitmap *bm, int orient)
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))
863 if (tmap_drawer_ptr != draw_tmap)
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
874 ogl_setActiveTexture(1);
875 glEnable(GL_TEXTURE_2D);
877 ogl_texwrap(bm->gltexture,GL_REPEAT);
879 #ifdef GL_NV_register_combiners
880 if (ogl_nv_register_combiners_ok)
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);
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
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);
908 if (bm->bm_flags & BM_FLAG_SUPER_TRANSPARENT)
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);
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);
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
936 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
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);
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);
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);
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);
958 //add up alpha channels
959 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
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);
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);
972 // GL_DECAL works sorta ok but the top texture is fullbright.
973 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
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);
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);
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);
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);
996 glBegin(GL_TRIANGLE_FAN);
1000 u1=1.0-f2glf(uvl_list[c].v);
1001 v1=f2glf(uvl_list[c].u);
1004 u1=1.0-f2glf(uvl_list[c].u);
1005 v1=1.0-f2glf(uvl_list[c].v);
1008 u1=f2glf(uvl_list[c].v);
1009 v1=1.0-f2glf(uvl_list[c].u);
1012 u1=f2glf(uvl_list[c].u);
1013 v1=f2glf(uvl_list[c].v);
1016 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1019 l=f2fl(uvl_list[c].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));
1029 //ogl_setActiveTexture(1); // still the active texture
1030 #ifdef GL_NV_register_combiners
1031 if (ogl_nv_register_combiners_ok)
1033 glDisable(GL_REGISTER_COMBINERS_NV);
1038 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1040 glDisable(GL_TEXTURE_2D);
1041 ogl_setActiveTexture(0);
1049 g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
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);
1056 ogl_texwrap(bm->gltexture,GL_REPEAT);
1057 glBegin(GL_TRIANGLE_FAN);
1061 u1=1.0-f2glf(uvl_list[c].v);
1062 v1=f2glf(uvl_list[c].u);
1065 u1=1.0-f2glf(uvl_list[c].u);
1066 v1=1.0-f2glf(uvl_list[c].v);
1069 u1=f2glf(uvl_list[c].v);
1070 v1=1.0-f2glf(uvl_list[c].u);
1073 u1=f2glf(uvl_list[c].u);
1074 v1=f2glf(uvl_list[c].v);
1077 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1080 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
1081 l=f2fl(uvl_list[c].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));
1094 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
1097 vms_vector pv,v1;//,v2;
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));
1104 OGL_ENABLE(TEXTURE_2D);
1106 ogl_texwrap(bm->gltexture,GL_CLAMP);
1109 glColor3f(1.0,1.0,1.0);
1110 width = fixmul(width,Matrix_scale.x);
1111 height = fixmul(height,Matrix_scale.y);
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));
1119 glTexCoord2f(0.0, 0.0);
1124 glTexCoord2f(bm->gltexture->u, 0.0);
1129 glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
1134 glTexCoord2f(0.0, bm->gltexture->v);
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));
1152 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
1154 GLfloat xo,yo,xf,yf;
1155 GLfloat u1,u2,v1,v2;
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;
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));
1167 /* glEnABLE(ALPHA_TEST);
1168 glAlphaFunc(GL_GREATER,0.0);*/
1170 OGL_ENABLE(TEXTURE_2D);
1172 ogl_texwrap(bm->gltexture,GL_CLAMP);
1176 if (bm->bm_w==bm->gltexture->w)
1177 u2=bm->gltexture->u;
1179 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1181 u1=bm->bm_x/(float)bm->gltexture->tw;
1182 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1186 if (bm->bm_h==bm->gltexture->h)
1187 v2=bm->gltexture->v;
1189 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1191 v1=bm->bm_y/(float)bm->gltexture->th;
1192 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1197 glColor3f(1.0,1.0,1.0);
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);
1205 // glDisABLE(ALPHA_TEST);
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);
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)
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));
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;
1230 // OGL_ENABLE(TEXTURE_2D);
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);
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)
1243 GLfloat xo,yo,xs,ys;
1244 GLfloat u1,v1;//,u2,v2;
1246 // unsigned char *oldpal;
1249 ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA);
1251 tex.lw=src->bm_rowsize;
1253 /* if (w==src->bm_w && sx==0){
1256 u1=sx/(float)src->bm_w*src->glu;
1257 u2=w/(float)src->bm_w*src->glu+u1;
1259 if (h==src->bm_h && sy==0){
1262 v1=sy/(float)src->bm_h*src->glv;
1263 v2=h/(float)src->bm_h*src->glv+v1;
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;
1274 OGL_ENABLE(TEXTURE_2D);
1277 ogl_pal=gr_current_pal;
1278 ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags, 0);
1281 OGL_BINDTEXTURE(tex.handle);
1283 ogl_texwrap(&tex,GL_CLAMP);
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);
1292 ogl_freetexture(&tex);
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);
1299 bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1301 unsigned char *d,*s;
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");
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);
1316 memset(texbuf,0,w1*h1*3);
1320 d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1321 s=texbuf+((h1-(i+sy+1))*w1+sx)*3;
1323 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1330 unsigned char *d,*s,*e;
1331 if (w*h*3>OGLTEXBUFSIZE)
1332 Error("ogl_ubitblt_tolinear: size larger than OGLTEXBUFSIZE\n");
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);
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;
1347 s=texbuf+w*(h-(i+1))*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);
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);
1363 d+=dest->bm_rowsize;
1365 glmprintf((0,"c=%i w*h=%i\n",c,w*h));
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;
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;
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);
1393 grs_canvas *offscreen_save_canv = NULL, *offscreen_canv = NULL;
1395 void ogl_start_offscreen_render(int x, int y, int w, int h)
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);
1404 void ogl_end_offscreen_render(void)
1408 if (!offscreen_canv)
1409 Error("ogl_end_offscreen_render: no offscreen_canv");
1411 glDrawBuffer(GL_FRONT);
1412 glReadBuffer(GL_BACK);
1413 OGL_DISABLE(TEXTURE_2D);
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);
1421 gr_free_sub_canvas(offscreen_canv);
1422 gr_set_current_canvas(offscreen_save_canv);
1423 offscreen_canv=NULL;
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;
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
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);
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);
1461 void merge_textures_stats(void);
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);
1467 // merge_textures_stats();
1468 // ogl_texture_stats();
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);
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
1489 ogl_swap_buffers_internal();
1490 glClear(GL_COLOR_BUFFER_BIT);
1493 void ogl_init_shared_palette(void)
1495 #ifdef GL_EXT_paletted_texture
1496 if (ogl_shared_palette_ok)
1500 glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1501 //glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, ogl_pal);
1503 for (i = 0; i < 256; i++)
1507 texbuf[i * 4] = 255;
1508 texbuf[i * 4 + 1] = 255;
1509 texbuf[i * 4 + 2] = 255;
1510 texbuf[i * 4 + 3] = 0;
1515 texbuf[i * 4 + 1] = 0;
1516 texbuf[i * 4 + 2] = 0;
1517 texbuf[i * 4 + 3] = 0;
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;
1527 glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
1532 int tex_format_supported(int iformat,int format){
1535 if (!ogl_intensity4_ok) return 0; break;
1536 case GL_LUMINANCE4_ALPHA4:
1537 if (!ogl_luminance4_alpha4_ok) return 0; break;
1539 if (!ogl_rgba2_ok) return 0; break;
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,
1548 return (internalFormat==iformat);
1553 //little hack to find the largest or equal multiple of 2 for a given number
1556 for (i=2;i<=4096;i*=2)
1561 //GLubyte texbuf[512*512*4];
1562 GLubyte texbuf[OGLTEXBUFSIZE];
1564 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 // GLushort *tex=(GLushort *)texp;
1568 if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
1569 Error("texture toobig %i %i",twidth,theight);
1572 for (y=0;y<theight;y++){
1573 i=dxo+truewidth*(y+dyo);
1574 for (x=0;x<twidth;x++){
1575 if (x<width && y<height)
1580 for (j = 0; j < data_format; ++j)
1581 (*(texp++)) = data[i * data_format + j];
1588 c = 256; // fill the pad space with transparency (or blackness)
1589 if (c == 254 && (bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1593 case GL_LUMINANCE_ALPHA:
1601 (*(texp++)) = 0; // transparent pixel
1603 case GL_COLOR_INDEX:
1607 Error("ogl_filltexbuf unhandled super-transparent texformat\n");
1611 else if ((c == 255 && (bm_flags & BM_FLAG_TRANSPARENT)) || c == 256)
1617 case GL_LUMINANCE_ALPHA:
1630 (*(texp++))=0;//transparent pixel
1632 case GL_COLOR_INDEX:
1636 Error("ogl_filltexbuf unknown texformat\n");
1641 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. :)
1644 case GL_LUMINANCE_ALPHA:
1649 (*(texp++)) = ogl_pal[c * 3] * 4;
1650 (*(texp++)) = ogl_pal[c * 3 + 1] * 4;
1651 (*(texp++)) = ogl_pal[c * 3 + 2] * 4;
1654 //(*(texp++))=gr_palette[c*3]*4;
1655 //(*(texp++))=gr_palette[c*3+1]*4;
1656 //(*(texp++))=gr_palette[c*3+2]*4;
1657 (*(texp++))=ogl_pal[c*3]*4;
1658 (*(texp++))=ogl_pal[c*3+1]*4;
1659 (*(texp++))=ogl_pal[c*3+2]*4;
1660 (*(texp++))=255;//not transparent
1661 // (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
1663 case GL_COLOR_INDEX:
1667 Error("ogl_filltexbuf unknown texformat\n");
1674 int tex_format_verify(ogl_texture *tex){
1675 while (!tex_format_supported(tex->internalformat,tex->format)){
1676 glmprintf((0,"tex format %x not supported",tex->internalformat));
1677 switch (tex->internalformat){
1679 if (ogl_luminance4_alpha4_ok){
1680 tex->internalformat=GL_LUMINANCE4_ALPHA4;
1681 tex->format=GL_LUMINANCE_ALPHA;
1683 }//note how it will fall through here if the statement is false
1684 case GL_LUMINANCE4_ALPHA4:
1686 tex->internalformat=GL_RGBA2;
1687 tex->format=GL_RGBA;
1689 }//note how it will fall through here if the statement is false
1691 tex->internalformat = ogl_rgba_internalformat;
1692 tex->format=GL_RGBA;
1695 mprintf((0,"...no tex format to fall back on\n"));
1698 glmprintf((0,"...falling back to %x\n",tex->internalformat));
1702 void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){
1704 if (tex->tw!=w || tex->th!=h){
1705 u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h);
1706 glmprintf((0,"shrunken texture?\n"));
1709 if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
1710 tex->bytes=((float)w*h*dbits)/8.0;
1711 tex->bytesu=((float)u*dbits)/8.0;
1713 tex->bytes=((float)w*h*bits)/8.0;
1714 tex->bytesu=((float)u*bits)/8.0;
1716 glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes));
1718 void tex_set_size(ogl_texture *tex){
1721 if (ogl_gettexlevelparam_ok){
1723 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w);
1724 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h);
1725 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t;
1726 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t;
1727 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t;
1728 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t;
1729 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t;
1730 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t;
1731 #ifdef GL_EXT_paletted_texture
1732 if (ogl_paletted_texture_ok)
1734 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INDEX_SIZE_EXT, &t);
1742 switch (tex->format){
1746 case GL_LUMINANCE_ALPHA:
1753 case GL_COLOR_INDEX:
1757 Error("tex_set_size unknown texformat\n");
1760 tex_set_size1(tex,bi,a,w,h);
1762 //loads a palettized bitmap into a ogl RGBA texture.
1763 //Sizes and pads dimensions to multiples of 2 if necessary.
1764 //In theory this could be a problem for repeating textures, but all real
1765 //textures (not sprites, etc) in descent are 64x64, so we are ok.
1766 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
1767 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format)
1769 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
1770 // int internalformat=GL_RGBA;
1771 // int format=GL_RGBA;
1773 tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
1774 // tex->tw=tex->w;tex->th=tex->h;//feeling lucky?
1776 if(gr_badtexture>0) return;
1778 #if !(defined(__APPLE__) && defined(__MACH__))
1779 // always fails on OS X, but textures work fine!
1780 if (tex_format_verify(tex))
1784 //calculate u/v values that would make the resulting texture correctly sized
1785 tex->u=(float)tex->w/(float)tex->tw;
1786 tex->v=(float)tex->h/(float)tex->th;
1788 #ifdef GL_EXT_paletted_texture
1789 if (ogl_shared_palette_ok && data_format == 0 && (tex->format == GL_RGBA || tex->format == GL_RGB) &&
1790 !(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.
1793 // descent makes palette entries 254 and 255 both do double duty, depending upon the setting of BM_FLAG_SUPER_TRANSPARENT and BM_FLAG_TRANSPARENT.
1794 // 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.)
1795 // We don't handle super transparent textures with ogl yet, so we don't bother checking that here.
1796 int usesthetransparentindexcolor = 0, usesthesupertransparentindexcolor = 0;
1798 if (!(bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1802 for (i = 0; i < tex->w * tex->h; ++i)
1804 usesthesupertransparentindexcolor += 1;
1806 if (!(bm_flags & BM_FLAG_TRANSPARENT))
1810 for (i=0; i < tex->w * tex->h; ++i)
1812 usesthetransparentindexcolor += 1;
1814 if (!usesthetransparentindexcolor && !usesthesupertransparentindexcolor)
1816 tex->internalformat = GL_COLOR_INDEX8_EXT;
1817 tex->format = GL_COLOR_INDEX;
1820 // printf("bm data=%p w=%i h=%i transparent:%i supertrans:%i\n", data, tex->w, tex->h, usesthetransparentindexcolor, usesthesupertransparentindexcolor);
1824 // if (width!=twidth || height!=theight)
1825 // glmprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
1826 ogl_filltexbuf(data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags, data_format);
1828 // Generate OpenGL texture IDs.
1829 glGenTextures(1, &tex->handle);
1832 glPrioritizeTextures(1,&tex->handle,&tex->prio);
1834 // Give our data to OpenGL.
1836 OGL_BINDTEXTURE(tex->handle);
1838 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1840 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1841 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1842 if (ogl_ext_texture_filter_anisotropic_ok && GL_texanisofilt)
1843 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_texanisofilt);
1847 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1848 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1850 // domipmap=0;//mipmaps aren't used in GL_NEAREST anyway, and making the mipmaps is pretty slow
1851 //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 if (tex->wantmip && GL_needmipmaps)
1854 gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
1855 tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
1857 glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
1858 tex->tw, tex->th, 0, tex->format, // RGBA textures.
1859 GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
1865 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));
1869 unsigned char decodebuf[512*512];
1871 void ogl_loadbmtexture_f(grs_bitmap *bm, int flags)
1876 while (bm->bm_parent)
1878 if (bm->gltexture && bm->gltexture->handle > 0)
1881 if ((bitmapname = piggy_game_bitmap_name(bm)))
1886 sprintf(filename, "textures/%s.png", bitmapname);
1887 if (read_png(filename, &pdata))
1889 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);
1890 if (pdata.depth == 8 && pdata.color)
1892 if (bm->gltexture == NULL)
1893 ogl_init_texture(bm->gltexture = ogl_get_free_texture(), pdata.width, pdata.height, flags | ((pdata.alpha) ? OGL_FLAG_ALPHA : 0));
1894 ogl_loadtexture(pdata.data, 0, 0, bm->gltexture, bm->bm_flags, pdata.paletted ? 0 : pdata.channels);
1897 free(pdata.palette);
1902 printf("%s: unsupported texture format: must be rgb, rgba, or paletted, and depth 8\n", filename);
1905 free(pdata.palette);
1909 if (bm->gltexture == NULL){
1910 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));
1913 if (bm->gltexture->handle>0)
1915 if (bm->gltexture->w==0){
1916 bm->gltexture->lw=bm->bm_w;
1917 bm->gltexture->w=bm->bm_w;
1918 bm->gltexture->h=bm->bm_h;
1921 if (bm->bm_flags & BM_FLAG_RLE){
1922 unsigned char * dbits;
1923 unsigned char * sbits;
1927 if (bm->bm_flags & BM_FLAG_RLE_BIG)
1930 sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)];
1933 for (i=0; i < bm->bm_h; i++ ) {
1934 gr_rle_decode(sbits,dbits);
1935 if ( bm->bm_flags & BM_FLAG_RLE_BIG )
1936 sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)])));
1938 sbits += (int)bm->bm_data[4+i];
1943 ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags, 0);
1946 void ogl_loadbmtexture(grs_bitmap *bm)
1948 ogl_loadbmtexture_f(bm, OGL_FLAG_MIPMAP);
1951 void ogl_freetexture(ogl_texture *gltexture)
1953 if (gltexture->handle>0) {
1955 glmprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
1956 glDeleteTextures( 1, &gltexture->handle );
1957 // gltexture->handle=0;
1958 ogl_reset_texture(gltexture);
1961 void ogl_freebmtexture(grs_bitmap *bm){
1963 ogl_freetexture(bm->gltexture);
1966 // glmprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
1967 // glDeleteTextures( 1, &bm->gltexture );
1968 // bm->gltexture=-1;