1 /* $Id: ogl.c,v 1.36 2004-11-14 09:50:36 schaffner 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"
54 //change to 1 for lots of spew.
56 #define glmprintf(a) mprintf(a)
65 #if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__) || defined(macintosh)
66 #define cosf(a) cos(a)
67 #define sinf(a) sin(a)
70 unsigned char *ogl_pal=gr_palette;
72 int GL_texmagfilt=GL_NEAREST;
73 int GL_texminfilt=GL_NEAREST;
74 float GL_texanisofilt = 0;
77 int last_width=-1,last_height=-1;
78 int GL_TEXTURE_2D_enabled=-1;
79 int GL_texclamp_enabled=-1;
81 extern int gr_badtexture;
82 int r_texcount = 0, r_cachedtexcount = 0;
83 int ogl_alttexmerge=1;//merge textures by just printing the seperate textures?
84 int ogl_rgba_internalformat = GL_RGBA8;
85 int ogl_rgb_internalformat = GL_RGB8;
86 int ogl_intensity4_ok=1;
87 int ogl_luminance4_alpha4_ok=1;
89 int ogl_readpixels_ok=1;
90 int ogl_gettexlevelparam_ok=1;
91 #ifdef GL_ARB_multitexture
92 int ogl_arb_multitexture_ok=0;
94 #ifdef GL_SGIS_multitexture
95 int ogl_sgis_multitexture_ok=0;
97 int ogl_nv_texture_env_combine4_ok = 0;
98 #ifdef GL_NV_register_combiners
99 int ogl_nv_register_combiners_ok = 0;
101 int ogl_ext_texture_filter_anisotropic_ok = 0;
102 #ifdef GL_EXT_paletted_texture
103 int ogl_shared_palette_ok = 0;
104 int ogl_paletted_texture_ok = 0;
108 int cross_lh[2]={0,0};
109 int primary_lh[3]={0,0,0};
110 int secondary_lh[5]={0,0,0,0,0};
113 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
114 else if(a!=lastbound) {glBindTexture(GL_TEXTURE_2D, a);lastbound=a;}*/
115 #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
116 else glBindTexture(GL_TEXTURE_2D, a);
119 ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE];
120 int ogl_texture_list_cur;
122 /* some function prototypes */
124 //#define OGLTEXBUFSIZE (1024*1024*4)
125 #define OGLTEXBUFSIZE (2048*2048*4)
126 extern GLubyte texbuf[OGLTEXBUFSIZE];
127 //void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int width,int height,int twidth,int theight);
128 void ogl_filltexbuf(unsigned char *data, GLubyte *texp, int truewidth, int width, int height, int dxo, int dyo, int twidth, int theight, int type, int bm_flags, int data_format);
129 void ogl_loadbmtexture(grs_bitmap *bm);
130 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,intdyo , int *texid,float *u,float *v,char domipmap,float prio);
131 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format);
132 void ogl_freetexture(ogl_texture *gltexture);
133 void ogl_do_palfx(void);
135 void ogl_init_texture_stats(ogl_texture* t){
136 t->prio=0.3;//default prio
140 void ogl_init_texture(ogl_texture* t, int w, int h, int flags)
143 if (flags & OGL_FLAG_NOCOLOR)
145 // use GL_INTENSITY instead of GL_RGB
146 if (flags & OGL_FLAG_ALPHA)
148 if (ogl_intensity4_ok)
150 t->internalformat = GL_INTENSITY4;
151 t->format = GL_LUMINANCE;
153 else if (ogl_luminance4_alpha4_ok)
155 t->internalformat = GL_LUMINANCE4_ALPHA4;
156 t->format = GL_LUMINANCE_ALPHA;
158 else if (ogl_rgba2_ok)
160 t->internalformat = GL_RGBA2;
165 t->internalformat = ogl_rgba_internalformat;
171 // there are certainly smaller formats we could use here, but nothing needs it ATM.
172 t->internalformat = ogl_rgb_internalformat;
178 if (flags & OGL_FLAG_ALPHA)
180 t->internalformat = ogl_rgba_internalformat;
185 t->internalformat = ogl_rgb_internalformat;
189 t->wrapstate[0] = -1;
190 t->wrapstate[1] = -1;
193 t->wantmip = flags & OGL_FLAG_MIPMAP;
194 ogl_init_texture_stats(t);
197 void ogl_reset_texture(ogl_texture* t)
199 ogl_init_texture(t, 0, 0, 0);
202 void ogl_reset_texture_stats_internal(void){
204 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
205 if (ogl_texture_list[i].handle>0){
206 ogl_init_texture_stats(&ogl_texture_list[i]);
209 void ogl_init_texture_list_internal(void){
211 ogl_texture_list_cur=0;
212 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
213 ogl_reset_texture(&ogl_texture_list[i]);
215 void ogl_smash_texture_list_internal(void){
218 memset(cross_lh,0,sizeof(cross_lh));
219 memset(primary_lh,0,sizeof(primary_lh));
220 memset(secondary_lh,0,sizeof(secondary_lh));
221 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
222 if (ogl_texture_list[i].handle>0){
223 glDeleteTextures( 1, &ogl_texture_list[i].handle );
224 ogl_texture_list[i].handle=0;
226 ogl_texture_list[i].wrapstate[0] = -1;
227 ogl_texture_list[i].wrapstate[1] = -1;
230 void ogl_vivify_texture_list_internal(void){
234 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
235 t=&ogl_texture_list[i];
236 if (t->w>0){//erk, realised this can't be done since we'd need the texture bm_data too. hmmm.
237 ogl_loadbmtexture(t);
242 ogl_texture* ogl_get_free_texture(void){
244 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
245 if (ogl_texture_list[ogl_texture_list_cur].handle<=0 && ogl_texture_list[ogl_texture_list_cur].w==0)
246 return &ogl_texture_list[ogl_texture_list_cur];
247 if (++ogl_texture_list_cur>=OGL_TEXTURE_LIST_SIZE)
248 ogl_texture_list_cur=0;
250 Error("OGL: texture list full!\n");
253 int ogl_texture_stats(void){
254 int used = 0, usedother = 0, usedidx = 0, usedrgb = 0, usedrgba = 0;
255 int databytes = 0, truebytes = 0, datatexel = 0, truetexel = 0, i;
256 int prio0=0,prio1=0,prio2=0,prio3=0,prioh=0;
259 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
260 t=&ogl_texture_list[i];
263 datatexel+=t->w*t->h;
264 truetexel+=t->tw*t->th;
265 databytes+=t->bytesu;
267 if (t->prio<0.299)prio0++;
268 else if (t->prio<0.399)prio1++;
269 else if (t->prio<0.499)prio2++;
270 else if (t->prio<0.599)prio3++;
272 if (t->format == GL_RGBA)
274 else if (t->format == GL_RGB)
276 else if (t->format == GL_COLOR_INDEX)
286 GLint idx, r, g, b, a, dbl, depth;
287 int res, colorsize, depthsize;
289 res = SWIDTH * SHEIGHT;
290 glGetIntegerv(GL_INDEX_BITS, &idx);
291 glGetIntegerv(GL_RED_BITS, &r);
292 glGetIntegerv(GL_GREEN_BITS, &g);
293 glGetIntegerv(GL_BLUE_BITS, &b);
294 glGetIntegerv(GL_ALPHA_BITS, &a);
295 glGetIntegerv(GL_DOUBLEBUFFER, &dbl);
297 glGetIntegerv(GL_DEPTH_BITS, &depth);
298 colorsize = (idx * res * dbl) / 8;
299 depthsize = res * depth / 8;
300 gr_printf(5, GAME_FONT->ft_h * 14 + 3 * 14, "%i(%i,%i,%i,%i) %iK(%iK wasted) (%i postcachedtex)", used, usedrgba, usedrgb, usedidx, usedother, truebytes / 1024, (truebytes - databytes) / 1024, r_texcount - r_cachedtexcount);
301 gr_printf(5, GAME_FONT->ft_h * 15 + 3 * 15, "%ibpp(r%i,g%i,b%i,a%i)x%i=%iK depth%i=%iK", idx, r, g, b, a, dbl, colorsize / 1024, depth, depthsize / 1024);
302 gr_printf(5, GAME_FONT->ft_h * 16 + 3 * 16, "total=%iK", (colorsize + depthsize + truebytes) / 1024);
304 // glmprintf((0,"ogl tex stats: %i(%i,%i|%i,%i,%i,%i,%i) %i(%i)b (%i(%i)wasted)\n",used,usedrgba,usedl4a4,prio0,prio1,prio2,prio3,prioh,truebytes,truetexel,truebytes-databytes,truetexel-datatexel));
307 int ogl_mem_target=-1;
308 void ogl_clean_texture_cache(void){
313 if (ogl_mem_target<0){
319 bytes=ogl_texture_stats();
320 while (bytes>ogl_mem_target){
321 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
322 t=&ogl_texture_list[i];
324 if (t->lastrend+f1_0*time<GameTime){
327 if (bytes<ogl_mem_target)
333 Error("not enough mem?");
338 void ogl_bindbmtex(grs_bitmap *bm){
339 if (bm->gltexture==NULL || bm->gltexture->handle<=0)
340 ogl_loadbmtexture(bm);
341 OGL_BINDTEXTURE(bm->gltexture->handle);
342 bm->gltexture->lastrend=GameTime;
343 bm->gltexture->numrend++;
344 //// if (bm->gltexture->numrend==80 || bm->gltexture->numrend==4000 || bm->gltexture->numrend==80000){
345 // if (bm->gltexture->numrend==100){
346 // bm->gltexture->prio+=0.1;
347 //// glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY,bm->gltexture->prio);
348 // glPrioritizeTextures(1,&bm->gltexture->handle,&bm->gltexture->prio);
351 //gltexture MUST be bound first
352 void ogl_texwrap(ogl_texture *gltexture,int state)
354 if (gltexture->wrapstate[active_texture_unit] != state || gltexture->numrend < 1)
356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state);
357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state);
358 gltexture->wrapstate[active_texture_unit] = state;
362 //crude texture precaching
363 //handles: powerups, walls, weapons, polymodels, etc.
364 //it is done with the horrid do_special_effects kludge so that sides that have to be texmerged and have animated textures will be correctly cached.
365 //similarly, with the objects(esp weapons), we could just go through and cache em all instead, but that would get ones that might not even be on the level
368 void ogl_cache_polymodel_textures(int model_num)
375 po = &Polygon_models[model_num];
376 for (i=0;i<po->n_textures;i++) {
377 // texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
378 ogl_loadbmtexture(&GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]);
381 void ogl_cache_vclip_textures(vclip *vc){
383 for (i=0;i<vc->num_frames;i++){
384 PIGGY_PAGE_IN(vc->frames[i]);
385 ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]);
389 void ogl_cache_vclipn_textures(int i)
391 if (i >= 0 && i < VCLIP_MAXNUM)
392 ogl_cache_vclip_textures(&Vclip[i]);
395 void ogl_cache_weapon_textures(int weapon_type)
401 w = &Weapon_info[weapon_type];
402 ogl_cache_vclipn_textures(w->flash_vclip);
403 ogl_cache_vclipn_textures(w->robot_hit_vclip);
404 ogl_cache_vclipn_textures(w->wall_hit_vclip);
405 if (w->render_type==WEAPON_RENDER_VCLIP)
406 ogl_cache_vclipn_textures(w->weapon_vclip);
407 else if (w->render_type == WEAPON_RENDER_POLYMODEL)
409 ogl_cache_polymodel_textures(w->model_num);
410 ogl_cache_polymodel_textures(w->model_num_inner);
414 void ogl_cache_level_textures(void)
423 ogl_reset_texture_stats_internal();//loading a new lev should reset textures
425 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
426 ogl_cache_vclipn_textures(Effects[i].dest_vclip);
427 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
429 if (ec->vc.num_frames>max_efx)
430 max_efx=ec->vc.num_frames;
432 glmprintf((0,"max_efx:%i\n",max_efx));
433 for (ef=0;ef<max_efx;ef++){
434 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
435 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
437 // if (ec->vc.num_frames>max_efx)
438 // max_efx=ec->vc.num_frames;
441 do_special_effects();
443 for (seg=0;seg<Num_segments;seg++){
444 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++){
445 sidep=&Segments[seg].sides[side];
446 tmap1=sidep->tmap_num;
447 tmap2=sidep->tmap_num2;
448 if (tmap1<0 || tmap1>=NumTextures){
449 glmprintf((0,"ogl_cache_level_textures %i %i %i %i\n",seg,side,tmap1,NumTextures));
453 PIGGY_PAGE_IN(Textures[tmap1]);
454 bm = &GameBitmaps[Textures[tmap1].index];
456 PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]);
457 bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index];
458 if (ogl_alttexmerge == 0 || (!OGL_SUPER_TRANSPARENT_OK && (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT)))
459 bm = texmerge_get_cached_bitmap( tmap1, tmap2 );
461 ogl_loadbmtexture(bm2);
463 // glmprintf((0,"ogl_cache_level_textures seg %i side %i t1 %i t2 %x bm %p NT %i\n",seg,side,tmap1,tmap2,bm,NumTextures));
465 ogl_loadbmtexture(bm);
468 glmprintf((0,"finished ef:%i\n",ef));
470 reset_special_effects();
471 init_special_effects();
475 // always have lasers, concs, flares. Always shows player appearance, and at least concs are always available to disappear.
476 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
477 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
478 ogl_cache_weapon_textures(FLARE_ID);
479 ogl_cache_vclipn_textures(VCLIP_PLAYER_APPEARANCE);
480 ogl_cache_vclipn_textures(VCLIP_POWERUP_DISAPPEARANCE);
481 ogl_cache_polymodel_textures(Player_ship->model_num);
482 ogl_cache_vclipn_textures(Player_ship->expl_vclip_num);
484 for (i=0;i<Highest_object_index;i++){
485 if(Objects[i].render_type==RT_POWERUP){
486 ogl_cache_vclipn_textures(Objects[i].rtype.vclip_info.vclip_num);
487 switch (Objects[i].id){
489 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
493 case POW_VULCAN_WEAPON:
494 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]);
496 case POW_SPREADFIRE_WEAPON:
497 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]);
499 case POW_PLASMA_WEAPON:
500 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]);
502 case POW_FUSION_WEAPON:
503 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]);
505 /* case POW_MISSILE_1:
507 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
509 case POW_PROXIMITY_WEAPON:
510 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]);
512 case POW_HOMING_AMMO_1:
513 case POW_HOMING_AMMO_4:
514 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]);
516 case POW_SMARTBOMB_WEAPON:
517 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]);
519 case POW_MEGA_WEAPON:
520 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]);
524 else if(Objects[i].render_type==RT_POLYOBJ){
525 //printf("robot %i model %i rmodel %i\n", Objects[i].id, Objects[i].rtype.pobj_info.model_num, Robot_info[Objects[i].id].model_num);
526 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp1_vclip_num);
527 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp2_vclip_num);
528 ogl_cache_weapon_textures(Robot_info[Objects[i].id].weapon_type);
529 ogl_cache_polymodel_textures(Objects[i].rtype.pobj_info.model_num);
533 glmprintf((0,"finished caching\n"));
534 r_cachedtexcount = r_texcount;
537 int r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc;
538 #define f2glf(x) (f2fl(x))
540 bool g3_draw_line(g3s_point *p0,g3s_point *p1)
543 c=grd_curcanv->cv_color;
544 OGL_DISABLE(TEXTURE_2D);
545 glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
547 glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));
548 glVertex3f(f2glf(p1->p3_vec.x),f2glf(p1->p3_vec.y),-f2glf(p1->p3_vec.z));
552 void ogl_drawcircle2(int nsides,int type,float xsc,float xo,float ysc,float yo){
556 for (i=0; i<nsides; i++) {
557 ang = 2.0*M_PI*i/nsides;
558 glVertex2f(cosf(ang)*xsc+xo,sinf(ang)*ysc+yo);
562 void ogl_drawcircle(int nsides,int type){
566 for (i=0; i<nsides; i++) {
567 ang = 2.0*M_PI*i/nsides;
568 glVertex2f(cosf(ang),sinf(ang));
572 int circle_list_init(int nsides,int type,int mode) {
573 int hand=glGenLists(1);
574 glNewList(hand, mode);
575 /* draw a unit radius circle in xy plane centered on origin */
576 ogl_drawcircle(nsides,type);
580 float bright_g[4]={ 32.0/256, 252.0/256, 32.0/256};
581 float dark_g[4]={ 32.0/256, 148.0/256, 32.0/256};
582 float darker_g[4]={ 32.0/256, 128.0/256, 32.0/256};
583 void ogl_draw_reticle(int cross,int primary,int secondary){
584 float scale=(float)Canvas_height/(float)grd_curscreen->sc_h;
586 // glTranslatef(0.5,0.5,0);
587 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);
588 glScalef(scale/320.0,scale/200.0,scale);//the positions are based upon the standard reticle at 320x200 res.
590 OGL_DISABLE(TEXTURE_2D);
592 if (!cross_lh[cross]){
593 cross_lh[cross]=glGenLists(1);
594 glNewList(cross_lh[cross], GL_COMPILE_AND_EXECUTE);
597 glColor3fv(darker_g);
598 glVertex2f(-4.0,4.0);
600 glColor3fv(bright_g);
603 glVertex2f(-2.0,2.0);
607 glVertex2f(-3.0,-2.0);
609 glColor3fv(bright_g);
610 glVertex2f(-2.0,-1.0);
613 glColor3fv(darker_g);
616 glColor3fv(bright_g);
623 glVertex2f(3.0,-2.0);
625 glColor3fv(bright_g);
626 glVertex2f(2.0,-1.0);
631 glCallList(cross_lh[cross]);
633 // if (Canvas_height>200)
634 // glLineWidth(Canvas_height/(float)200);
635 if (!primary_lh[primary]){
636 primary_lh[primary]=glGenLists(1);
637 glNewList(primary_lh[primary], GL_COMPILE_AND_EXECUTE);
642 glVertex2f(-14.0,-8.0);
643 glVertex2f(-8.0,-5.0);
645 glVertex2f(14.0,-8.0);
646 glVertex2f(8.0,-5.0);
651 glColor3fv(bright_g);
653 ogl_drawcircle2(6,GL_POLYGON,1.5,-7.0,1.5,-5.0);
655 ogl_drawcircle2(6,GL_POLYGON,1.5,7.0,1.5,-5.0);
659 glColor3fv(bright_g);
661 ogl_drawcircle2(4,GL_POLYGON,1.0,-14.0,1.0,-8.0);
663 ogl_drawcircle2(4,GL_POLYGON,1.0,14.0,1.0,-8.0);
667 glCallList(primary_lh[primary]);
668 // if (Canvas_height>200)
671 if (!secondary_lh[secondary]){
672 secondary_lh[secondary]=glGenLists(1);
673 glNewList(secondary_lh[secondary], GL_COMPILE_AND_EXECUTE);
677 glColor3fv(darker_g);
679 glColor3fv(bright_g);
680 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,-10.0,2.0,-1.0);
683 glColor3fv(darker_g);
685 glColor3fv(bright_g);
686 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,10.0,2.0,-1.0);
688 //bottom/middle secondary
690 glColor3fv(darker_g);
692 glColor3fv(bright_g);
693 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,0.0,2.0,-7.0);
697 glCallList(secondary_lh[secondary]);
701 int g3_draw_sphere(g3s_point *pnt,fix rad){
703 c=grd_curcanv->cv_color;
704 OGL_DISABLE(TEXTURE_2D);
705 // glPointSize(f2glf(rad));
706 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
707 // glBegin(GL_POINTS);
708 // glVertex3f(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
711 glTranslatef(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
712 glScalef(f2glf(rad),f2glf(rad),f2glf(rad));
713 if (!sphereh) sphereh=circle_list_init(20,GL_POLYGON,GL_COMPILE_AND_EXECUTE);
714 else glCallList(sphereh);
719 int gr_ucircle(fix xc1, fix yc1, fix r1)
722 c=grd_curcanv->cv_color;
723 OGL_DISABLE(TEXTURE_2D);
724 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
727 (f2fl(xc1) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width,
728 1.0 - (f2fl(yc1) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0);
729 glScalef(f2fl(r1) / last_width, f2fl(r1) / last_height, 1.0);
730 ogl_drawcircle(10 + 2 * (int)(M_PI * f2fl(r1) / 19), GL_LINE_LOOP);
734 int gr_circle(fix xc1,fix yc1,fix r1){
735 return gr_ucircle(xc1,yc1,r1);
738 bool g3_draw_poly(int nv,g3s_point **pointlist)
742 c=grd_curcanv->cv_color;
743 // 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);
744 OGL_DISABLE(TEXTURE_2D);
745 if (Gr_scanline_darkening_level >= GR_FADE_LEVELS)
746 glColor3f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c));
748 glColor4f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c), 1.0 - (float)Gr_scanline_darkening_level / ((float)GR_FADE_LEVELS - 1.0));
749 glBegin(GL_TRIANGLE_FAN);
751 // glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
752 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
758 void gr_upoly_tmap(int nverts, int *vert ){
759 mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
761 void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){
762 mprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called
764 extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist);
765 bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)
769 if (tmap_drawer_ptr==draw_tmap_flat){
770 /* fix average_light=0;
773 average_light += uvl_list[i].l;*/
774 OGL_DISABLE(TEXTURE_2D);
775 // glmprintf((0,"Gr_scanline_darkening_level=%i %f\n",Gr_scanline_darkening_level,Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
776 glColor4f(0,0,0,1.0-(Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
777 //glColor4f(0,0,0,f2fl(average_light/nv));
778 glBegin(GL_TRIANGLE_FAN);
780 // glColor4f(0,0,0,f2fl(uvl_list[c].l));
781 // glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
782 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
785 }else if (tmap_drawer_ptr==draw_tmap){
787 /* if (bm->bm_w !=64||bm->bm_h!=64)
788 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
789 OGL_ENABLE(TEXTURE_2D);
791 ogl_texwrap(bm->gltexture,GL_REPEAT);
792 glBegin(GL_TRIANGLE_FAN);
794 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
797 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
798 l=f2fl(uvl_list[c].l);
801 glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
802 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
803 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
807 mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
812 int active_texture_unit = 0;
814 void ogl_setActiveTexture(int t)
816 if (ogl_arb_multitexture_ok)
818 #ifdef GL_ARB_multitexture
820 glActiveTextureARB(GL_TEXTURE0_ARB);
822 glActiveTextureARB(GL_TEXTURE1_ARB);
825 else if (ogl_sgis_multitexture_ok)
827 #ifdef GL_SGIS_multitexture
829 glSelectTextureSGIS(GL_TEXTURE0_SGIS);
831 glSelectTextureSGIS(GL_TEXTURE1_SGIS);
834 active_texture_unit = t;
837 void ogl_MultiTexCoord2f(int t, float u, float v)
839 if (ogl_arb_multitexture_ok)
841 #ifdef GL_ARB_multitexture
843 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
845 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
848 else if (ogl_sgis_multitexture_ok)
850 #ifdef GL_SGIS_multitexture
852 glMultiTexCoord2fSGIS(GL_TEXTURE0_SGIS, u, v);
854 glMultiTexCoord2fSGIS(GL_TEXTURE1_SGIS, u, v);
859 bool g3_draw_tmap_2(int nv, g3s_point **pointlist, g3s_uvl *uvl_list, grs_bitmap *bmbot, grs_bitmap *bm, int orient)
861 #if ((defined(GL_NV_register_combiners) || defined(GL_NV_texture_env_combine4)) && (defined(GL_ARB_multitexture) || defined(GL_SGIS_multitexture)))
862 if ((/*ogl_nv_register_combiners_ok ||*/ ogl_nv_texture_env_combine4_ok) && (ogl_arb_multitexture_ok || ogl_sgis_multitexture_ok))
867 if (tmap_drawer_ptr != draw_tmap)
872 //ogl_setActiveTexture(0);
873 OGL_ENABLE(TEXTURE_2D);
874 ogl_bindbmtex(bmbot);
875 ogl_texwrap(bmbot->gltexture, GL_REPEAT);
876 // GL_MODULATE is fine for texture 0
878 ogl_setActiveTexture(1);
879 glEnable(GL_TEXTURE_2D);
881 ogl_texwrap(bm->gltexture,GL_REPEAT);
883 #ifdef GL_NV_register_combiners
884 if (ogl_nv_register_combiners_ok)
886 glEnable(GL_REGISTER_COMBINERS_NV);
887 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
888 // spare0 = tex0 * (1-alpha1) + tex1 * alpha1
889 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
890 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
891 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
892 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
894 GL_COMBINER0_NV, //GLenum stage
895 GL_RGB, //GLenum portion,
896 GL_DISCARD_NV, //GLenum abOutput,
897 GL_DISCARD_NV, //GLenum cdOutput,
898 GL_SPARE0_NV, //GLenum sumOutput,
899 GL_NONE, //GLenum scale,
900 GL_NONE, //GLenum bias,
901 GL_FALSE, //GLboolean abDotProduct,
902 GL_FALSE, //GLboolean cdDotProduct,
903 GL_FALSE //GLboolean muxSum
905 // out = spare0 * color
906 // ( out = AB + (1-A)C + D )
907 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
908 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
909 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
910 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
912 if (bm->bm_flags & BM_FLAG_SUPER_TRANSPARENT)
914 // out = alpha0*(1-tex1) + alpha1
915 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
916 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_BLUE);
917 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
918 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
922 // out = alpha0 + alpha1
923 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
924 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
925 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
926 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
929 GL_COMBINER0_NV, //GLenum stage
930 GL_ALPHA, //GLenum portion,
931 GL_DISCARD_NV, //GLenum abOutput,
932 GL_DISCARD_NV, //GLenum cdOutput,
933 GL_SPARE0_NV, //GLenum sumOutput,
934 GL_NONE, //GLenum scale,
935 GL_NONE, //GLenum bias,
936 GL_FALSE, //GLboolean abDotProduct,
937 GL_FALSE, //GLboolean cdDotProduct,
938 GL_FALSE //GLboolean muxSum
940 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
945 //http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_env_combine4.txt
946 //only GL_NV_texture_env_combine4 lets us do what we need:
947 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
949 //multiply top texture by color(vertex lighting) and add bottom texture(where alpha says to)
950 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
952 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
953 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
954 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE);
955 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_EXT);
957 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
958 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
959 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
960 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
962 //add up alpha channels
963 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
965 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
966 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
967 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PREVIOUS_EXT);
968 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
970 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
971 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
972 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
973 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
976 // GL_DECAL works sorta ok but the top texture is fullbright.
977 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
979 // GL_ARB_texture_env_combine comes close, but doesn't quite make it.
980 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
982 //// this gives effect like GL_DECAL:
983 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
984 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
985 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
986 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
989 // this properly shades the top texture, but the bottom texture doesn't get through.
990 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
991 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
992 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
996 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
997 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
998 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
1000 glBegin(GL_TRIANGLE_FAN);
1004 u1=1.0-f2glf(uvl_list[c].v);
1005 v1=f2glf(uvl_list[c].u);
1008 u1=1.0-f2glf(uvl_list[c].u);
1009 v1=1.0-f2glf(uvl_list[c].v);
1012 u1=f2glf(uvl_list[c].v);
1013 v1=1.0-f2glf(uvl_list[c].u);
1016 u1=f2glf(uvl_list[c].u);
1017 v1=f2glf(uvl_list[c].v);
1020 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1023 l=f2fl(uvl_list[c].l);
1026 ogl_MultiTexCoord2f(0, f2glf(uvl_list[c].u), f2glf(uvl_list[c].v));
1027 ogl_MultiTexCoord2f(1, u1, v1);
1028 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1029 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1030 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1033 //ogl_setActiveTexture(1); // still the active texture
1034 #ifdef GL_NV_register_combiners
1035 if (ogl_nv_register_combiners_ok)
1037 glDisable(GL_REGISTER_COMBINERS_NV);
1042 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1044 glDisable(GL_TEXTURE_2D);
1045 ogl_setActiveTexture(0);
1053 g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
1056 /* if (bm->bm_w !=64||bm->bm_h!=64)
1057 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
1058 OGL_ENABLE(TEXTURE_2D);
1060 ogl_texwrap(bm->gltexture,GL_REPEAT);
1061 glBegin(GL_TRIANGLE_FAN);
1065 u1=1.0-f2glf(uvl_list[c].v);
1066 v1=f2glf(uvl_list[c].u);
1069 u1=1.0-f2glf(uvl_list[c].u);
1070 v1=1.0-f2glf(uvl_list[c].v);
1073 u1=f2glf(uvl_list[c].v);
1074 v1=1.0-f2glf(uvl_list[c].u);
1077 u1=f2glf(uvl_list[c].u);
1078 v1=f2glf(uvl_list[c].v);
1081 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1084 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
1085 l=f2fl(uvl_list[c].l);
1088 glTexCoord2f(u1,v1);
1089 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1090 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1091 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1098 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
1101 vms_vector pv,v1;//,v2;
1105 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1106 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1108 OGL_ENABLE(TEXTURE_2D);
1110 ogl_texwrap(bm->gltexture,GL_CLAMP);
1113 glColor3f(1.0,1.0,1.0);
1114 width = fixmul(width,Matrix_scale.x);
1115 height = fixmul(height,Matrix_scale.y);
1117 // g3_rotate_point(&p[i],pos);
1118 vm_vec_sub(&v1,pos,&View_position);
1119 vm_vec_rotate(&pv,&v1,&View_matrix);
1120 // printf(" %f,%f,%f->",f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1123 glTexCoord2f(0.0, 0.0);
1128 glTexCoord2f(bm->gltexture->u, 0.0);
1133 glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
1138 glTexCoord2f(0.0, bm->gltexture->v);
1143 // vm_vec_rotate(&v2,&v1,&View_matrix);
1144 // vm_vec_sub(&v1,&v2,&pv);
1145 //vm_vec_sub(&v1,&pv,&v2);
1146 // vm_vec_sub(&v2,&pv,&v1);
1147 glVertex3f(f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1148 // printf("%f,%f,%f ",f2glf(v1.x),f2glf(v1.y),-f2glf(v1.z));
1156 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
1158 GLfloat xo,yo,xf,yf;
1159 GLfloat u1,u2,v1,v2;
1161 x+=grd_curcanv->cv_bitmap.bm_x;
1162 y+=grd_curcanv->cv_bitmap.bm_y;
1163 xo=x/(float)last_width;
1164 xf=(bm->bm_w+x)/(float)last_width;
1165 yo=1.0-y/(float)last_height;
1166 yf=1.0-(bm->bm_h+y)/(float)last_height;
1168 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1169 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1171 /* glEnABLE(ALPHA_TEST);
1172 glAlphaFunc(GL_GREATER,0.0);*/
1174 OGL_ENABLE(TEXTURE_2D);
1176 ogl_texwrap(bm->gltexture,GL_CLAMP);
1180 if (bm->bm_w==bm->gltexture->w)
1181 u2=bm->gltexture->u;
1183 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1185 u1=bm->bm_x/(float)bm->gltexture->tw;
1186 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1190 if (bm->bm_h==bm->gltexture->h)
1191 v2=bm->gltexture->v;
1193 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1195 v1=bm->bm_y/(float)bm->gltexture->th;
1196 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1201 glColor3f(1.0,1.0,1.0);
1203 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
1204 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1205 glTexCoord2f(u2, v1); glVertex2f(xf, yo);
1206 glTexCoord2f(u2, v2); glVertex2f(xf, yf);
1207 glTexCoord2f(u1, v2); glVertex2f(xo, yf);
1209 // glDisABLE(ALPHA_TEST);
1213 bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){
1214 return ogl_ubitmapm_c(x,y,bm,-1);
1215 // return ogl_ubitblt(bm->bm_w,bm->bm_h,x,y,0,0,bm,NULL);
1218 //also upsidedown, currently.
1219 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1221 GLfloat xo,yo;//,xs,ys;
1222 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));
1227 xo=dx/(float)last_width;
1228 // xo=dx/(float)grd_curscreen->sc_w;
1229 // xs=w/(float)last_width;
1230 //yo=1.0-dy/(float)last_height;
1231 yo=1.0-(dy+h)/(float)last_height;
1232 // ys=h/(float)last_height;
1234 // OGL_ENABLE(TEXTURE_2D);
1236 OGL_DISABLE(TEXTURE_2D);
1237 glRasterPos2f(xo,yo);
1238 ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h,GL_RGBA);
1239 glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);
1245 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)
1247 GLfloat xo,yo,xs,ys;
1248 GLfloat u1,v1;//,u2,v2;
1250 // unsigned char *oldpal;
1253 ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA);
1255 tex.lw=src->bm_rowsize;
1257 /* if (w==src->bm_w && sx==0){
1260 u1=sx/(float)src->bm_w*src->glu;
1261 u2=w/(float)src->bm_w*src->glu+u1;
1263 if (h==src->bm_h && sy==0){
1266 v1=sy/(float)src->bm_h*src->glv;
1267 v2=h/(float)src->bm_h*src->glv+v1;
1273 xo=dx/(float)last_width;
1274 xs=dw/(float)last_width;
1275 yo=1.0-dy/(float)last_height;
1276 ys=dh/(float)last_height;
1278 OGL_ENABLE(TEXTURE_2D);
1281 ogl_pal=gr_current_pal;
1282 ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags, 0);
1285 OGL_BINDTEXTURE(tex.handle);
1287 ogl_texwrap(&tex,GL_CLAMP);
1290 glColor3f(1.0,1.0,1.0);
1291 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1292 glTexCoord2f(tex.u, v1); glVertex2f(xo+xs, yo);
1293 glTexCoord2f(tex.u, tex.v); glVertex2f(xo+xs, yo-ys);
1294 glTexCoord2f(u1, tex.v); glVertex2f(xo, yo-ys);
1296 ogl_freetexture(&tex);
1299 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1300 return ogl_ubitblt_i(w,h,dx,dy,w,h,sx,sy,src,dest);
1303 bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1305 unsigned char *d,*s;
1309 w1=grd_curscreen->sc_w;h1=grd_curscreen->sc_h;
1310 if (w1*h1*3>OGLTEXBUFSIZE)
1311 Error("ogl_ubitblt_tolinear: screen res larger than OGLTEXBUFSIZE\n");
1313 if (ogl_readpixels_ok>0){
1314 OGL_DISABLE(TEXTURE_2D);
1315 glReadBuffer(GL_FRONT);
1316 glReadPixels(0,0,w1,h1,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1317 // glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1318 // glReadPixels(sx,sy,w+sx,h+sy,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1320 memset(texbuf,0,w1*h1*3);
1324 d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1325 s=texbuf+((h1-(i+sy+1))*w1+sx)*3;
1327 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1334 unsigned char *d,*s,*e;
1335 if (w*h*3>OGLTEXBUFSIZE)
1336 Error("ogl_ubitblt_tolinear: size larger than OGLTEXBUFSIZE\n");
1339 #if 1//also seems to cause a mess. need to look into it a bit more..
1340 if (ogl_readpixels_ok>0){
1341 OGL_DISABLE(TEXTURE_2D);
1342 glReadBuffer(GL_FRONT);
1343 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1344 glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1347 memset(texbuf,0,w*h*3);
1348 // d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1349 d=dest->bm_data+dx+dy*dest->bm_rowsize;
1351 s=texbuf+w*(h-(i+1))*3;
1353 if (s<texbuf){Error("blah1\n");}
1354 if (d<dest->bm_data){Error("blah3\n");}
1355 // d=dest->bm_data+(i*dest->bm_rowsize);
1359 if (s>texbuf+w*h*3-3){Error("blah2\n");}
1360 if (d>dest->bm_data+dest->bm_rowsize*(h+dy)+dx ){Error("blah4\n");}
1361 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1367 d+=dest->bm_rowsize;
1369 glmprintf((0,"c=%i w*h=%i\n",c,w*h));
1374 bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1375 #if 0 //just seems to cause a mess.
1376 GLfloat xo,yo;//,xs,ys;
1381 // xo=dx/(float)last_width;
1382 xo=dx/(float)grd_curscreen->sc_w;
1383 // yo=1.0-(dy+h)/(float)last_height;
1384 yo=1.0-(dy+h)/(float)grd_curscreen->sc_h;
1387 OGL_DISABLE(TEXTURE_2D);
1388 glReadBuffer(GL_FRONT);
1389 glRasterPos2f(xo,yo);
1390 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1391 glCopyPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_COLOR);
1397 grs_canvas *offscreen_save_canv = NULL, *offscreen_canv = NULL;
1399 void ogl_start_offscreen_render(int x, int y, int w, int h)
1402 Error("ogl_start_offscreen_render: offscreen_canv!=NULL");
1403 offscreen_save_canv = grd_curcanv;
1404 offscreen_canv = gr_create_sub_canvas(grd_curcanv, x, y, w, h);
1405 gr_set_current_canvas(offscreen_canv);
1406 glDrawBuffer(GL_BACK);
1408 void ogl_end_offscreen_render(void)
1412 if (!offscreen_canv)
1413 Error("ogl_end_offscreen_render: no offscreen_canv");
1415 glDrawBuffer(GL_FRONT);
1416 glReadBuffer(GL_BACK);
1417 OGL_DISABLE(TEXTURE_2D);
1419 y = last_height - offscreen_canv->cv_bitmap.bm_y - offscreen_canv->cv_bitmap.bm_h;
1420 glRasterPos2f(offscreen_canv->cv_bitmap.bm_x/(float)last_width, y/(float)last_height);
1421 glCopyPixels(offscreen_canv->cv_bitmap.bm_x, y,
1422 offscreen_canv->cv_bitmap.bm_w,
1423 offscreen_canv->cv_bitmap.bm_h, GL_COLOR);
1425 gr_free_sub_canvas(offscreen_canv);
1426 gr_set_current_canvas(offscreen_save_canv);
1427 offscreen_canv=NULL;
1430 void ogl_start_frame(void){
1431 r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;
1432 // gl_badtexture=500;
1434 OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);
1435 glClearColor(0.0, 0.0, 0.0, 0.0);
1436 // glEnable(GL_ALPHA_TEST);
1437 // glAlphaFunc(GL_GREATER,0.01);
1438 glShadeModel(GL_SMOOTH);
1439 glMatrixMode(GL_PROJECTION);
1440 glLoadIdentity();//clear matrix
1441 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1442 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),0.01,1000000.0);
1443 gluPerspective(90.0,1.0,0.01,1000000.0);
1444 //gluPerspective(90.0,(GLfloat)(Canvas_width*3)/(GLfloat)(Canvas_height*4),0.01,1000000.0);
1445 // gluPerspective(75.0,(GLfloat)Canvas_width/(GLfloat)Canvas_height,1.0,1000000.0);
1446 glMatrixMode(GL_MODELVIEW);
1447 glLoadIdentity();//clear matrix
1449 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1450 // glDisABLE(DITHER);
1451 // glScalef(1.0,1.0,-1.0);
1452 // glScalef(1.0,1.0,-1.0);
1455 // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1456 // OGL_TEXENV(GL_TEXTURE_ENV_MODE,GL_MODULATE);
1457 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1458 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1459 // OGL_TEXPARAM(GL_TEXTURE_MAG_FILTER,GL_texmagfilt);
1460 // OGL_TEXPARAM(GL_TEXTURE_MIN_FILTER,GL_texminfilt);
1461 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1462 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1465 void merge_textures_stats(void);
1467 void ogl_end_frame(void){
1468 // OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);
1469 OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1471 // merge_textures_stats();
1472 // ogl_texture_stats();
1474 // glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1475 glMatrixMode(GL_PROJECTION);
1476 glLoadIdentity();//clear matrix
1477 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
1478 glMatrixMode(GL_MODELVIEW);
1479 glLoadIdentity();//clear matrix
1480 // glDisABLE(BLEND);
1481 //glDisABLE(ALPHA_TEST);
1482 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1483 // ogl_swap_buffers();//platform specific code
1484 // glClear(GL_COLOR_BUFFER_BIT);
1486 void ogl_swap_buffers(void){
1487 ogl_clean_texture_cache();
1488 if (gr_renderstats){
1489 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);
1490 // 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
1493 ogl_swap_buffers_internal();
1494 glClear(GL_COLOR_BUFFER_BIT);
1497 void ogl_init_shared_palette(void)
1499 #ifdef GL_EXT_paletted_texture
1500 if (ogl_shared_palette_ok)
1504 glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1505 //glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, ogl_pal);
1507 for (i = 0; i < 256; i++)
1511 texbuf[i * 4] = 255;
1512 texbuf[i * 4 + 1] = 255;
1513 texbuf[i * 4 + 2] = 255;
1514 texbuf[i * 4 + 3] = 0;
1519 texbuf[i * 4 + 1] = 0;
1520 texbuf[i * 4 + 2] = 0;
1521 texbuf[i * 4 + 3] = 0;
1525 texbuf[i * 4] = gr_current_pal[i * 3] * 4;
1526 texbuf[i * 4 + 1] = gr_current_pal[i * 3 + 1] * 4;
1527 texbuf[i * 4 + 2] = gr_current_pal[i * 3 + 2] * 4;
1528 texbuf[i * 4 + 3] = 255;
1531 glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
1536 int tex_format_supported(int iformat,int format){
1539 if (!ogl_intensity4_ok) return 0; break;
1540 case GL_LUMINANCE4_ALPHA4:
1541 if (!ogl_luminance4_alpha4_ok) return 0; break;
1543 if (!ogl_rgba2_ok) return 0; break;
1545 if (ogl_gettexlevelparam_ok){
1546 GLint internalFormat;
1547 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, iformat, 64, 64, 0,
1548 format, GL_UNSIGNED_BYTE, texbuf);//NULL?
1549 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
1550 GL_TEXTURE_INTERNAL_FORMAT,
1552 return (internalFormat==iformat);
1557 //little hack to find the largest or equal multiple of 2 for a given number
1561 for (i = 1; i <= 4096; i *= 2)
1566 //GLubyte texbuf[512*512*4];
1567 GLubyte texbuf[OGLTEXBUFSIZE];
1569 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)
1571 // GLushort *tex=(GLushort *)texp;
1573 if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
1574 Error("texture toobig %i %i",twidth,theight);
1577 for (y=0;y<theight;y++){
1578 i=dxo+truewidth*(y+dyo);
1579 for (x=0;x<twidth;x++){
1580 if (x<width && y<height)
1585 for (j = 0; j < data_format; ++j)
1586 (*(texp++)) = data[i * data_format + j];
1593 c = 256; // fill the pad space with transparency (or blackness)
1594 if (c == 254 && (bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1598 case GL_LUMINANCE_ALPHA:
1606 (*(texp++)) = 0; // transparent pixel
1608 case GL_COLOR_INDEX:
1612 Error("ogl_filltexbuf unhandled super-transparent texformat\n");
1616 else if ((c == 255 && (bm_flags & BM_FLAG_TRANSPARENT)) || c == 256)
1622 case GL_LUMINANCE_ALPHA:
1635 (*(texp++))=0;//transparent pixel
1637 case GL_COLOR_INDEX:
1641 Error("ogl_filltexbuf unknown texformat\n");
1646 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. :)
1649 case GL_LUMINANCE_ALPHA:
1654 (*(texp++)) = ogl_pal[c * 3] * 4;
1655 (*(texp++)) = ogl_pal[c * 3 + 1] * 4;
1656 (*(texp++)) = ogl_pal[c * 3 + 2] * 4;
1659 //(*(texp++))=gr_palette[c*3]*4;
1660 //(*(texp++))=gr_palette[c*3+1]*4;
1661 //(*(texp++))=gr_palette[c*3+2]*4;
1662 (*(texp++))=ogl_pal[c*3]*4;
1663 (*(texp++))=ogl_pal[c*3+1]*4;
1664 (*(texp++))=ogl_pal[c*3+2]*4;
1665 (*(texp++))=255;//not transparent
1666 // (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
1668 case GL_COLOR_INDEX:
1672 Error("ogl_filltexbuf unknown texformat\n");
1680 int tex_format_verify(ogl_texture *tex){
1681 while (!tex_format_supported(tex->internalformat,tex->format)){
1682 glmprintf((0,"tex format %x not supported",tex->internalformat));
1683 switch (tex->internalformat){
1685 if (ogl_luminance4_alpha4_ok){
1686 tex->internalformat=GL_LUMINANCE4_ALPHA4;
1687 tex->format=GL_LUMINANCE_ALPHA;
1689 }//note how it will fall through here if the statement is false
1690 case GL_LUMINANCE4_ALPHA4:
1692 tex->internalformat=GL_RGBA2;
1693 tex->format=GL_RGBA;
1695 }//note how it will fall through here if the statement is false
1697 #if defined(__APPLE__) && defined(__MACH__)
1698 case GL_RGB8: // Quartz doesn't support RGB only
1700 tex->internalformat = ogl_rgba_internalformat;
1701 tex->format=GL_RGBA;
1704 mprintf((0,"...no tex format to fall back on\n"));
1707 glmprintf((0,"...falling back to %x\n",tex->internalformat));
1711 void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){
1713 if (tex->tw!=w || tex->th!=h){
1714 u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h);
1715 glmprintf((0,"shrunken texture?\n"));
1718 if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
1719 tex->bytes=((float)w*h*dbits)/8.0;
1720 tex->bytesu=((float)u*dbits)/8.0;
1722 tex->bytes=((float)w*h*bits)/8.0;
1723 tex->bytesu=((float)u*bits)/8.0;
1725 glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes));
1727 void tex_set_size(ogl_texture *tex){
1730 if (ogl_gettexlevelparam_ok){
1732 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w);
1733 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h);
1734 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t;
1735 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t;
1736 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t;
1737 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t;
1738 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t;
1739 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t;
1740 #ifdef GL_EXT_paletted_texture
1741 if (ogl_paletted_texture_ok)
1743 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INDEX_SIZE_EXT, &t);
1751 switch (tex->format){
1755 case GL_LUMINANCE_ALPHA:
1762 case GL_COLOR_INDEX:
1766 Error("tex_set_size unknown texformat\n");
1769 tex_set_size1(tex,bi,a,w,h);
1771 //loads a palettized bitmap into a ogl RGBA texture.
1772 //Sizes and pads dimensions to multiples of 2 if necessary.
1773 //In theory this could be a problem for repeating textures, but all real
1774 //textures (not sprites, etc) in descent are 64x64, so we are ok.
1775 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
1776 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format)
1778 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
1779 // int internalformat=GL_RGBA;
1780 // int format=GL_RGBA;
1782 tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
1783 // tex->tw=tex->w;tex->th=tex->h;//feeling lucky?
1785 if(gr_badtexture>0) return;
1787 if (tex_format_verify(tex))
1790 //calculate u/v values that would make the resulting texture correctly sized
1791 tex->u=(float)tex->w/(float)tex->tw;
1792 tex->v=(float)tex->h/(float)tex->th;
1794 #ifdef GL_EXT_paletted_texture
1795 if (ogl_shared_palette_ok && data_format == 0 && (tex->format == GL_RGBA || tex->format == GL_RGB) &&
1796 !(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.
1799 // descent makes palette entries 254 and 255 both do double duty, depending upon the setting of BM_FLAG_SUPER_TRANSPARENT and BM_FLAG_TRANSPARENT.
1800 // 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.)
1801 // We don't handle super transparent textures with ogl yet, so we don't bother checking that here.
1802 int usesthetransparentindexcolor = 0, usesthesupertransparentindexcolor = 0;
1804 if (!(bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1808 for (i = 0; i < tex->w * tex->h; ++i)
1810 usesthesupertransparentindexcolor += 1;
1812 if (!(bm_flags & BM_FLAG_TRANSPARENT))
1816 for (i=0; i < tex->w * tex->h; ++i)
1818 usesthetransparentindexcolor += 1;
1820 if (!usesthetransparentindexcolor && !usesthesupertransparentindexcolor)
1822 tex->internalformat = GL_COLOR_INDEX8_EXT;
1823 tex->format = GL_COLOR_INDEX;
1826 // printf("bm data=%p w=%i h=%i transparent:%i supertrans:%i\n", data, tex->w, tex->h, usesthetransparentindexcolor, usesthesupertransparentindexcolor);
1830 // if (width!=twidth || height!=theight)
1831 // glmprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
1832 ogl_filltexbuf(data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags, data_format);
1834 // Generate OpenGL texture IDs.
1835 glGenTextures(1, &tex->handle);
1838 glPrioritizeTextures(1,&tex->handle,&tex->prio);
1840 // Give our data to OpenGL.
1842 OGL_BINDTEXTURE(tex->handle);
1844 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1847 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1848 if (ogl_ext_texture_filter_anisotropic_ok && GL_texanisofilt)
1849 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_texanisofilt);
1853 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1854 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1856 // domipmap=0;//mipmaps aren't used in GL_NEAREST anyway, and making the mipmaps is pretty slow
1857 //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.
1859 if (tex->wantmip && GL_needmipmaps)
1860 gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
1861 tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
1863 glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
1864 tex->tw, tex->th, 0, tex->format, // RGBA textures.
1865 GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
1871 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));
1875 unsigned char decodebuf[512*512];
1877 void ogl_loadbmtexture_f(grs_bitmap *bm, int flags)
1884 while (bm->bm_parent)
1886 if (bm->gltexture && bm->gltexture->handle > 0)
1890 if ((bitmapname = piggy_game_bitmap_name(bm)))
1895 sprintf(filename, "textures/%s.png", bitmapname);
1896 if (read_png(filename, &pdata))
1898 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);
1899 if (pdata.depth == 8 && pdata.color)
1901 if (bm->gltexture == NULL)
1902 ogl_init_texture(bm->gltexture = ogl_get_free_texture(), pdata.width, pdata.height, flags | ((pdata.alpha || bm->bm_flags & BM_FLAG_TRANSPARENT) ? OGL_FLAG_ALPHA : 0));
1903 ogl_loadtexture(pdata.data, 0, 0, bm->gltexture, bm->bm_flags, pdata.paletted ? 0 : pdata.channels);
1906 free(pdata.palette);
1911 printf("%s: unsupported texture format: must be rgb, rgba, or paletted, and depth 8\n", filename);
1914 free(pdata.palette);
1919 if (bm->gltexture == NULL){
1920 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));
1923 if (bm->gltexture->handle>0)
1925 if (bm->gltexture->w==0){
1926 bm->gltexture->lw=bm->bm_w;
1927 bm->gltexture->w=bm->bm_w;
1928 bm->gltexture->h=bm->bm_h;
1931 if (bm->bm_flags & BM_FLAG_RLE){
1932 unsigned char * dbits;
1933 unsigned char * sbits;
1937 if (bm->bm_flags & BM_FLAG_RLE_BIG)
1940 sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)];
1943 for (i=0; i < bm->bm_h; i++ ) {
1944 gr_rle_decode(sbits,dbits);
1945 if ( bm->bm_flags & BM_FLAG_RLE_BIG )
1946 sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)])));
1948 sbits += (int)bm->bm_data[4+i];
1953 ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags, 0);
1956 void ogl_loadbmtexture(grs_bitmap *bm)
1958 ogl_loadbmtexture_f(bm, OGL_FLAG_MIPMAP);
1961 void ogl_freetexture(ogl_texture *gltexture)
1963 if (gltexture->handle>0) {
1965 glmprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
1966 glDeleteTextures( 1, &gltexture->handle );
1967 // gltexture->handle=0;
1968 ogl_reset_texture(gltexture);
1971 void ogl_freebmtexture(grs_bitmap *bm){
1973 ogl_freetexture(bm->gltexture);
1976 // glmprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
1977 // glDeleteTextures( 1, &bm->gltexture );
1978 // bm->gltexture=-1;