1 /* $Id: ogl.c,v 1.32 2004-05-23 00:21:03 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"
54 //change to 1 for lots of spew.
56 #define glmprintf(a) mprintf(a)
65 #if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__)
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 ogl_init_texture_stats(t);
196 void ogl_reset_texture(ogl_texture* t)
198 ogl_init_texture(t, 0, 0, 0);
201 void ogl_reset_texture_stats_internal(void){
203 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
204 if (ogl_texture_list[i].handle>0){
205 ogl_init_texture_stats(&ogl_texture_list[i]);
208 void ogl_init_texture_list_internal(void){
210 ogl_texture_list_cur=0;
211 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
212 ogl_reset_texture(&ogl_texture_list[i]);
214 void ogl_smash_texture_list_internal(void){
217 memset(cross_lh,0,sizeof(cross_lh));
218 memset(primary_lh,0,sizeof(primary_lh));
219 memset(secondary_lh,0,sizeof(secondary_lh));
220 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
221 if (ogl_texture_list[i].handle>0){
222 glDeleteTextures( 1, &ogl_texture_list[i].handle );
223 ogl_texture_list[i].handle=0;
225 ogl_texture_list[i].wrapstate[0] = -1;
226 ogl_texture_list[i].wrapstate[1] = -1;
229 void ogl_vivify_texture_list_internal(void){
233 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
234 t=&ogl_texture_list[i];
235 if (t->w>0){//erk, realised this can't be done since we'd need the texture bm_data too. hmmm.
236 ogl_loadbmtexture(t);
241 ogl_texture* ogl_get_free_texture(void){
243 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
244 if (ogl_texture_list[ogl_texture_list_cur].handle<=0 && ogl_texture_list[ogl_texture_list_cur].w==0)
245 return &ogl_texture_list[ogl_texture_list_cur];
246 if (++ogl_texture_list_cur>=OGL_TEXTURE_LIST_SIZE)
247 ogl_texture_list_cur=0;
249 Error("OGL: texture list full!\n");
252 int ogl_texture_stats(void){
253 int used = 0, usedother = 0, usedidx = 0, usedrgb = 0, usedrgba = 0;
254 int databytes = 0, truebytes = 0, datatexel = 0, truetexel = 0, i;
255 int prio0=0,prio1=0,prio2=0,prio3=0,prioh=0;
258 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
259 t=&ogl_texture_list[i];
262 datatexel+=t->w*t->h;
263 truetexel+=t->tw*t->th;
264 databytes+=t->bytesu;
266 if (t->prio<0.299)prio0++;
267 else if (t->prio<0.399)prio1++;
268 else if (t->prio<0.499)prio2++;
269 else if (t->prio<0.599)prio3++;
271 if (t->format == GL_RGBA)
273 else if (t->format == GL_RGB)
275 else if (t->format == GL_COLOR_INDEX)
285 int idx, r, g, b, a, dbl, depth, res, colorsize, depthsize;
287 res = SWIDTH * SHEIGHT;
288 glGetIntegerv(GL_INDEX_BITS, &idx);
289 glGetIntegerv(GL_RED_BITS, &r);
290 glGetIntegerv(GL_GREEN_BITS, &g);
291 glGetIntegerv(GL_BLUE_BITS, &b);
292 glGetIntegerv(GL_ALPHA_BITS, &a);
293 glGetIntegerv(GL_DOUBLEBUFFER, &dbl);
295 glGetIntegerv(GL_DEPTH_BITS, &depth);
296 colorsize = (idx * res * dbl) / 8;
297 depthsize = res * depth / 8;
298 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);
299 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);
300 gr_printf(5, GAME_FONT->ft_h * 16 + 3 * 16, "total=%iK", (colorsize + depthsize + truebytes) / 1024);
302 // glmprintf((0,"ogl tex stats: %i(%i,%i|%i,%i,%i,%i,%i) %i(%i)b (%i(%i)wasted)\n",used,usedrgba,usedl4a4,prio0,prio1,prio2,prio3,prioh,truebytes,truetexel,truebytes-databytes,truetexel-datatexel));
305 int ogl_mem_target=-1;
306 void ogl_clean_texture_cache(void){
311 if (ogl_mem_target<0){
317 bytes=ogl_texture_stats();
318 while (bytes>ogl_mem_target){
319 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
320 t=&ogl_texture_list[i];
322 if (t->lastrend+f1_0*time<GameTime){
325 if (bytes<ogl_mem_target)
331 Error("not enough mem?");
336 void ogl_bindbmtex(grs_bitmap *bm){
337 if (bm->gltexture==NULL || bm->gltexture->handle<=0)
338 ogl_loadbmtexture(bm);
339 OGL_BINDTEXTURE(bm->gltexture->handle);
340 bm->gltexture->lastrend=GameTime;
341 bm->gltexture->numrend++;
342 //// if (bm->gltexture->numrend==80 || bm->gltexture->numrend==4000 || bm->gltexture->numrend==80000){
343 // if (bm->gltexture->numrend==100){
344 // bm->gltexture->prio+=0.1;
345 //// glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY,bm->gltexture->prio);
346 // glPrioritizeTextures(1,&bm->gltexture->handle,&bm->gltexture->prio);
349 //gltexture MUST be bound first
350 void ogl_texwrap(ogl_texture *gltexture,int state)
352 if (gltexture->wrapstate[active_texture_unit] != state || gltexture->numrend < 1)
354 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state);
355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state);
356 gltexture->wrapstate[active_texture_unit] = state;
360 //crude texture precaching
361 //handles: powerups, walls, weapons, polymodels, etc.
362 //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.
363 //similarly, with the objects(esp weapons), we could just go through and cache em all instead, but that would get ones that might not even be on the level
366 void ogl_cache_polymodel_textures(int model_num)
373 po = &Polygon_models[model_num];
374 for (i=0;i<po->n_textures;i++) {
375 // texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
376 ogl_loadbmtexture(&GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]);
379 void ogl_cache_vclip_textures(vclip *vc){
381 for (i=0;i<vc->num_frames;i++){
382 PIGGY_PAGE_IN(vc->frames[i]);
383 ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]);
387 void ogl_cache_vclipn_textures(int i)
389 if (i >= 0 && i < VCLIP_MAXNUM)
390 ogl_cache_vclip_textures(&Vclip[i]);
393 void ogl_cache_weapon_textures(int weapon_type)
399 w = &Weapon_info[weapon_type];
400 ogl_cache_vclipn_textures(w->flash_vclip);
401 ogl_cache_vclipn_textures(w->robot_hit_vclip);
402 ogl_cache_vclipn_textures(w->wall_hit_vclip);
403 if (w->render_type==WEAPON_RENDER_VCLIP)
404 ogl_cache_vclipn_textures(w->weapon_vclip);
405 else if (w->render_type == WEAPON_RENDER_POLYMODEL)
407 ogl_cache_polymodel_textures(w->model_num);
408 ogl_cache_polymodel_textures(w->model_num_inner);
412 void ogl_cache_level_textures(void)
421 ogl_reset_texture_stats_internal();//loading a new lev should reset textures
423 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
424 ogl_cache_vclipn_textures(Effects[i].dest_vclip);
425 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
427 if (ec->vc.num_frames>max_efx)
428 max_efx=ec->vc.num_frames;
430 glmprintf((0,"max_efx:%i\n",max_efx));
431 for (ef=0;ef<max_efx;ef++){
432 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
433 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
435 // if (ec->vc.num_frames>max_efx)
436 // max_efx=ec->vc.num_frames;
439 do_special_effects();
441 for (seg=0;seg<Num_segments;seg++){
442 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++){
443 sidep=&Segments[seg].sides[side];
444 tmap1=sidep->tmap_num;
445 tmap2=sidep->tmap_num2;
446 if (tmap1<0 || tmap1>=NumTextures){
447 glmprintf((0,"ogl_cache_level_textures %i %i %i %i\n",seg,side,tmap1,NumTextures));
451 PIGGY_PAGE_IN(Textures[tmap1]);
452 bm = &GameBitmaps[Textures[tmap1].index];
454 PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]);
455 bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index];
456 if (ogl_alttexmerge == 0 || (!OGL_SUPER_TRANSPARENT_OK && (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT)))
457 bm = texmerge_get_cached_bitmap( tmap1, tmap2 );
459 ogl_loadbmtexture(bm2);
461 // 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));
463 ogl_loadbmtexture(bm);
466 glmprintf((0,"finished ef:%i\n",ef));
468 reset_special_effects();
469 init_special_effects();
473 // always have lasers, concs, flares. Always shows player appearance, and at least concs are always available to disappear.
474 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
475 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
476 ogl_cache_weapon_textures(FLARE_ID);
477 ogl_cache_vclipn_textures(VCLIP_PLAYER_APPEARANCE);
478 ogl_cache_vclipn_textures(VCLIP_POWERUP_DISAPPEARANCE);
479 ogl_cache_polymodel_textures(Player_ship->model_num);
480 ogl_cache_vclipn_textures(Player_ship->expl_vclip_num);
482 for (i=0;i<Highest_object_index;i++){
483 if(Objects[i].render_type==RT_POWERUP){
484 ogl_cache_vclipn_textures(Objects[i].rtype.vclip_info.vclip_num);
485 switch (Objects[i].id){
487 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
491 case POW_VULCAN_WEAPON:
492 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]);
494 case POW_SPREADFIRE_WEAPON:
495 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]);
497 case POW_PLASMA_WEAPON:
498 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]);
500 case POW_FUSION_WEAPON:
501 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]);
503 /* case POW_MISSILE_1:
505 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
507 case POW_PROXIMITY_WEAPON:
508 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]);
510 case POW_HOMING_AMMO_1:
511 case POW_HOMING_AMMO_4:
512 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]);
514 case POW_SMARTBOMB_WEAPON:
515 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]);
517 case POW_MEGA_WEAPON:
518 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]);
522 else if(Objects[i].render_type==RT_POLYOBJ){
523 //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);
524 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp1_vclip_num);
525 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp2_vclip_num);
526 ogl_cache_weapon_textures(Robot_info[Objects[i].id].weapon_type);
527 ogl_cache_polymodel_textures(Objects[i].rtype.pobj_info.model_num);
531 glmprintf((0,"finished caching\n"));
532 r_cachedtexcount = r_texcount;
535 int r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc;
536 #define f2glf(x) (f2fl(x))
538 bool g3_draw_line(g3s_point *p0,g3s_point *p1)
541 c=grd_curcanv->cv_color;
542 OGL_DISABLE(TEXTURE_2D);
543 glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
545 glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));
546 glVertex3f(f2glf(p1->p3_vec.x),f2glf(p1->p3_vec.y),-f2glf(p1->p3_vec.z));
550 void ogl_drawcircle2(int nsides,int type,float xsc,float xo,float ysc,float yo){
554 for (i=0; i<nsides; i++) {
555 ang = 2.0*M_PI*i/nsides;
556 glVertex2f(cosf(ang)*xsc+xo,sinf(ang)*ysc+yo);
560 void ogl_drawcircle(int nsides,int type){
564 for (i=0; i<nsides; i++) {
565 ang = 2.0*M_PI*i/nsides;
566 glVertex2f(cosf(ang),sinf(ang));
570 int circle_list_init(int nsides,int type,int mode) {
571 int hand=glGenLists(1);
572 glNewList(hand, mode);
573 /* draw a unit radius circle in xy plane centered on origin */
574 ogl_drawcircle(nsides,type);
578 float bright_g[4]={ 32.0/256, 252.0/256, 32.0/256};
579 float dark_g[4]={ 32.0/256, 148.0/256, 32.0/256};
580 float darker_g[4]={ 32.0/256, 128.0/256, 32.0/256};
581 void ogl_draw_reticle(int cross,int primary,int secondary){
582 float scale=(float)Canvas_height/(float)grd_curscreen->sc_h;
584 // glTranslatef(0.5,0.5,0);
585 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);
586 glScalef(scale/320.0,scale/200.0,scale);//the positions are based upon the standard reticle at 320x200 res.
588 OGL_DISABLE(TEXTURE_2D);
590 if (!cross_lh[cross]){
591 cross_lh[cross]=glGenLists(1);
592 glNewList(cross_lh[cross], GL_COMPILE_AND_EXECUTE);
595 glColor3fv(darker_g);
596 glVertex2f(-4.0,4.0);
598 glColor3fv(bright_g);
601 glVertex2f(-2.0,2.0);
605 glVertex2f(-3.0,-2.0);
607 glColor3fv(bright_g);
608 glVertex2f(-2.0,-1.0);
611 glColor3fv(darker_g);
614 glColor3fv(bright_g);
621 glVertex2f(3.0,-2.0);
623 glColor3fv(bright_g);
624 glVertex2f(2.0,-1.0);
629 glCallList(cross_lh[cross]);
631 // if (Canvas_height>200)
632 // glLineWidth(Canvas_height/(float)200);
633 if (!primary_lh[primary]){
634 primary_lh[primary]=glGenLists(1);
635 glNewList(primary_lh[primary], GL_COMPILE_AND_EXECUTE);
640 glVertex2f(-14.0,-8.0);
641 glVertex2f(-8.0,-5.0);
643 glVertex2f(14.0,-8.0);
644 glVertex2f(8.0,-5.0);
649 glColor3fv(bright_g);
651 ogl_drawcircle2(6,GL_POLYGON,1.5,-7.0,1.5,-5.0);
653 ogl_drawcircle2(6,GL_POLYGON,1.5,7.0,1.5,-5.0);
657 glColor3fv(bright_g);
659 ogl_drawcircle2(4,GL_POLYGON,1.0,-14.0,1.0,-8.0);
661 ogl_drawcircle2(4,GL_POLYGON,1.0,14.0,1.0,-8.0);
665 glCallList(primary_lh[primary]);
666 // if (Canvas_height>200)
669 if (!secondary_lh[secondary]){
670 secondary_lh[secondary]=glGenLists(1);
671 glNewList(secondary_lh[secondary], GL_COMPILE_AND_EXECUTE);
675 glColor3fv(darker_g);
677 glColor3fv(bright_g);
678 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,-10.0,2.0,-1.0);
681 glColor3fv(darker_g);
683 glColor3fv(bright_g);
684 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,10.0,2.0,-1.0);
686 //bottom/middle secondary
688 glColor3fv(darker_g);
690 glColor3fv(bright_g);
691 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,0.0,2.0,-7.0);
695 glCallList(secondary_lh[secondary]);
699 int g3_draw_sphere(g3s_point *pnt,fix rad){
701 c=grd_curcanv->cv_color;
702 OGL_DISABLE(TEXTURE_2D);
703 // glPointSize(f2glf(rad));
704 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
705 // glBegin(GL_POINTS);
706 // glVertex3f(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
709 glTranslatef(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
710 glScalef(f2glf(rad),f2glf(rad),f2glf(rad));
711 if (!sphereh) sphereh=circle_list_init(20,GL_POLYGON,GL_COMPILE_AND_EXECUTE);
712 else glCallList(sphereh);
717 int gr_ucircle(fix xc1, fix yc1, fix r1)
720 c=grd_curcanv->cv_color;
721 OGL_DISABLE(TEXTURE_2D);
722 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
725 (f2fl(xc1) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width,
726 1.0 - (f2fl(yc1) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0);
727 glScalef(f2fl(r1) / last_width, f2fl(r1) / last_height, 1.0);
728 ogl_drawcircle(10 + 2 * (int)(M_PI * f2fl(r1) / 19), GL_LINE_LOOP);
732 int gr_circle(fix xc1,fix yc1,fix r1){
733 return gr_ucircle(xc1,yc1,r1);
736 bool g3_draw_poly(int nv,g3s_point **pointlist)
740 c=grd_curcanv->cv_color;
741 // 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);
742 OGL_DISABLE(TEXTURE_2D);
743 if (Gr_scanline_darkening_level >= GR_FADE_LEVELS)
744 glColor3f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c));
746 glColor4f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c), 1.0 - (float)Gr_scanline_darkening_level / ((float)GR_FADE_LEVELS - 1.0));
747 glBegin(GL_TRIANGLE_FAN);
749 // glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
750 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
756 void gr_upoly_tmap(int nverts, int *vert ){
757 mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
759 void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){
760 mprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called
762 extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist);
763 bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)
767 if (tmap_drawer_ptr==draw_tmap_flat){
768 /* fix average_light=0;
771 average_light += uvl_list[i].l;*/
772 OGL_DISABLE(TEXTURE_2D);
773 // glmprintf((0,"Gr_scanline_darkening_level=%i %f\n",Gr_scanline_darkening_level,Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
774 glColor4f(0,0,0,1.0-(Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
775 //glColor4f(0,0,0,f2fl(average_light/nv));
776 glBegin(GL_TRIANGLE_FAN);
778 // glColor4f(0,0,0,f2fl(uvl_list[c].l));
779 // glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
780 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
783 }else if (tmap_drawer_ptr==draw_tmap){
785 /* if (bm->bm_w !=64||bm->bm_h!=64)
786 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
787 OGL_ENABLE(TEXTURE_2D);
789 ogl_texwrap(bm->gltexture,GL_REPEAT);
790 glBegin(GL_TRIANGLE_FAN);
792 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
795 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
796 l=f2fl(uvl_list[c].l);
799 glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
800 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
801 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
805 mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
810 int active_texture_unit = 0;
812 void ogl_setActiveTexture(int t)
814 if (ogl_arb_multitexture_ok)
816 #ifdef GL_ARB_multitexture
818 glActiveTextureARB(GL_TEXTURE0_ARB);
820 glActiveTextureARB(GL_TEXTURE1_ARB);
823 else if (ogl_sgis_multitexture_ok)
825 #ifdef GL_SGIS_multitexture
827 glSelectTextureSGIS(GL_TEXTURE0_SGIS);
829 glSelectTextureSGIS(GL_TEXTURE1_SGIS);
832 active_texture_unit = t;
835 void ogl_MultiTexCoord2f(int t, float u, float v)
837 if (ogl_arb_multitexture_ok)
839 #ifdef GL_ARB_multitexture
841 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
843 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
846 else if (ogl_sgis_multitexture_ok)
848 #ifdef GL_SGIS_multitexture
850 glMultiTexCoord2fSGIS(GL_TEXTURE0_SGIS, u, v);
852 glMultiTexCoord2fSGIS(GL_TEXTURE1_SGIS, u, v);
857 bool g3_draw_tmap_2(int nv, g3s_point **pointlist, g3s_uvl *uvl_list, grs_bitmap *bmbot, grs_bitmap *bm, int orient)
859 #if ((defined(GL_NV_register_combiners) || defined(GL_NV_texture_env_combine4)) && (defined(GL_ARB_multitexture) || defined(GL_SGIS_multitexture)))
860 if ((/*ogl_nv_register_combiners_ok ||*/ ogl_nv_texture_env_combine4_ok) && (ogl_arb_multitexture_ok || ogl_sgis_multitexture_ok))
865 if (tmap_drawer_ptr != draw_tmap)
870 //ogl_setActiveTexture(0);
871 OGL_ENABLE(TEXTURE_2D);
872 ogl_bindbmtex(bmbot);
873 ogl_texwrap(bmbot->gltexture, GL_REPEAT);
874 // GL_MODULATE is fine for texture 0
876 ogl_setActiveTexture(1);
877 glEnable(GL_TEXTURE_2D);
879 ogl_texwrap(bm->gltexture,GL_REPEAT);
881 #ifdef GL_NV_register_combiners
882 if (ogl_nv_register_combiners_ok)
884 glEnable(GL_REGISTER_COMBINERS_NV);
885 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
886 // spare0 = tex0 * (1-alpha1) + tex1 * alpha1
887 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
888 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
889 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
890 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
892 GL_COMBINER0_NV, //GLenum stage
893 GL_RGB, //GLenum portion,
894 GL_DISCARD_NV, //GLenum abOutput,
895 GL_DISCARD_NV, //GLenum cdOutput,
896 GL_SPARE0_NV, //GLenum sumOutput,
897 GL_NONE, //GLenum scale,
898 GL_NONE, //GLenum bias,
899 GL_FALSE, //GLboolean abDotProduct,
900 GL_FALSE, //GLboolean cdDotProduct,
901 GL_FALSE //GLboolean muxSum
903 // out = spare0 * color
904 // ( out = AB + (1-A)C + D )
905 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
906 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
907 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
908 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
910 if (bm->bm_flags & BM_FLAG_SUPER_TRANSPARENT)
912 // out = alpha0*(1-tex1) + alpha1
913 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
914 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_BLUE);
915 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
916 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
920 // out = alpha0 + alpha1
921 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
922 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
923 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
924 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
927 GL_COMBINER0_NV, //GLenum stage
928 GL_ALPHA, //GLenum portion,
929 GL_DISCARD_NV, //GLenum abOutput,
930 GL_DISCARD_NV, //GLenum cdOutput,
931 GL_SPARE0_NV, //GLenum sumOutput,
932 GL_NONE, //GLenum scale,
933 GL_NONE, //GLenum bias,
934 GL_FALSE, //GLboolean abDotProduct,
935 GL_FALSE, //GLboolean cdDotProduct,
936 GL_FALSE //GLboolean muxSum
938 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
943 //http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_env_combine4.txt
944 //only GL_NV_texture_env_combine4 lets us do what we need:
945 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
947 //multiply top texture by color(vertex lighting) and add bottom texture(where alpha says to)
948 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
950 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
951 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
952 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE);
953 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_EXT);
955 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
956 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
957 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
958 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
960 //add up alpha channels
961 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
963 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
964 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
965 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PREVIOUS_EXT);
966 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
968 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
969 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
970 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
971 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
974 // GL_DECAL works sorta ok but the top texture is fullbright.
975 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
977 // GL_ARB_texture_env_combine comes close, but doesn't quite make it.
978 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
980 //// this gives effect like GL_DECAL:
981 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
982 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
983 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
984 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
987 // this properly shades the top texture, but the bottom texture doesn't get through.
988 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
989 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
990 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
994 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
995 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
996 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
998 glBegin(GL_TRIANGLE_FAN);
1002 u1=1.0-f2glf(uvl_list[c].v);
1003 v1=f2glf(uvl_list[c].u);
1006 u1=1.0-f2glf(uvl_list[c].u);
1007 v1=1.0-f2glf(uvl_list[c].v);
1010 u1=f2glf(uvl_list[c].v);
1011 v1=1.0-f2glf(uvl_list[c].u);
1014 u1=f2glf(uvl_list[c].u);
1015 v1=f2glf(uvl_list[c].v);
1018 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1021 l=f2fl(uvl_list[c].l);
1024 ogl_MultiTexCoord2f(0, f2glf(uvl_list[c].u), f2glf(uvl_list[c].v));
1025 ogl_MultiTexCoord2f(1, u1, v1);
1026 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1027 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1028 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1031 //ogl_setActiveTexture(1); // still the active texture
1032 #ifdef GL_NV_register_combiners
1033 if (ogl_nv_register_combiners_ok)
1035 glDisable(GL_REGISTER_COMBINERS_NV);
1040 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1042 glDisable(GL_TEXTURE_2D);
1043 ogl_setActiveTexture(0);
1051 g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
1054 /* if (bm->bm_w !=64||bm->bm_h!=64)
1055 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
1056 OGL_ENABLE(TEXTURE_2D);
1058 ogl_texwrap(bm->gltexture,GL_REPEAT);
1059 glBegin(GL_TRIANGLE_FAN);
1063 u1=1.0-f2glf(uvl_list[c].v);
1064 v1=f2glf(uvl_list[c].u);
1067 u1=1.0-f2glf(uvl_list[c].u);
1068 v1=1.0-f2glf(uvl_list[c].v);
1071 u1=f2glf(uvl_list[c].v);
1072 v1=1.0-f2glf(uvl_list[c].u);
1075 u1=f2glf(uvl_list[c].u);
1076 v1=f2glf(uvl_list[c].v);
1079 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1082 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
1083 l=f2fl(uvl_list[c].l);
1086 glTexCoord2f(u1,v1);
1087 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1088 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
1089 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1096 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
1099 vms_vector pv,v1;//,v2;
1103 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1104 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1106 OGL_ENABLE(TEXTURE_2D);
1108 ogl_texwrap(bm->gltexture,GL_CLAMP);
1111 glColor3f(1.0,1.0,1.0);
1112 width = fixmul(width,Matrix_scale.x);
1113 height = fixmul(height,Matrix_scale.y);
1115 // g3_rotate_point(&p[i],pos);
1116 vm_vec_sub(&v1,pos,&View_position);
1117 vm_vec_rotate(&pv,&v1,&View_matrix);
1118 // printf(" %f,%f,%f->",f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1121 glTexCoord2f(0.0, 0.0);
1126 glTexCoord2f(bm->gltexture->u, 0.0);
1131 glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
1136 glTexCoord2f(0.0, bm->gltexture->v);
1141 // vm_vec_rotate(&v2,&v1,&View_matrix);
1142 // vm_vec_sub(&v1,&v2,&pv);
1143 //vm_vec_sub(&v1,&pv,&v2);
1144 // vm_vec_sub(&v2,&pv,&v1);
1145 glVertex3f(f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1146 // printf("%f,%f,%f ",f2glf(v1.x),f2glf(v1.y),-f2glf(v1.z));
1154 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
1156 GLfloat xo,yo,xf,yf;
1157 GLfloat u1,u2,v1,v2;
1159 x+=grd_curcanv->cv_bitmap.bm_x;
1160 y+=grd_curcanv->cv_bitmap.bm_y;
1161 xo=x/(float)last_width;
1162 xf=(bm->bm_w+x)/(float)last_width;
1163 yo=1.0-y/(float)last_height;
1164 yf=1.0-(bm->bm_h+y)/(float)last_height;
1166 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1167 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1169 /* glEnABLE(ALPHA_TEST);
1170 glAlphaFunc(GL_GREATER,0.0);*/
1172 OGL_ENABLE(TEXTURE_2D);
1174 ogl_texwrap(bm->gltexture,GL_CLAMP);
1178 if (bm->bm_w==bm->gltexture->w)
1179 u2=bm->gltexture->u;
1181 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1183 u1=bm->bm_x/(float)bm->gltexture->tw;
1184 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1188 if (bm->bm_h==bm->gltexture->h)
1189 v2=bm->gltexture->v;
1191 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1193 v1=bm->bm_y/(float)bm->gltexture->th;
1194 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1199 glColor3f(1.0,1.0,1.0);
1201 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
1202 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1203 glTexCoord2f(u2, v1); glVertex2f(xf, yo);
1204 glTexCoord2f(u2, v2); glVertex2f(xf, yf);
1205 glTexCoord2f(u1, v2); glVertex2f(xo, yf);
1207 // glDisABLE(ALPHA_TEST);
1211 bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){
1212 return ogl_ubitmapm_c(x,y,bm,-1);
1213 // return ogl_ubitblt(bm->bm_w,bm->bm_h,x,y,0,0,bm,NULL);
1216 //also upsidedown, currently.
1217 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1219 GLfloat xo,yo;//,xs,ys;
1220 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));
1225 xo=dx/(float)last_width;
1226 // xo=dx/(float)grd_curscreen->sc_w;
1227 // xs=w/(float)last_width;
1228 //yo=1.0-dy/(float)last_height;
1229 yo=1.0-(dy+h)/(float)last_height;
1230 // ys=h/(float)last_height;
1232 // OGL_ENABLE(TEXTURE_2D);
1234 OGL_DISABLE(TEXTURE_2D);
1235 glRasterPos2f(xo,yo);
1236 ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h,GL_RGBA);
1237 glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);
1243 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)
1245 GLfloat xo,yo,xs,ys;
1246 GLfloat u1,v1;//,u2,v2;
1248 // unsigned char *oldpal;
1251 ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA);
1253 tex.lw=src->bm_rowsize;
1255 /* if (w==src->bm_w && sx==0){
1258 u1=sx/(float)src->bm_w*src->glu;
1259 u2=w/(float)src->bm_w*src->glu+u1;
1261 if (h==src->bm_h && sy==0){
1264 v1=sy/(float)src->bm_h*src->glv;
1265 v2=h/(float)src->bm_h*src->glv+v1;
1271 xo=dx/(float)last_width;
1272 xs=dw/(float)last_width;
1273 yo=1.0-dy/(float)last_height;
1274 ys=dh/(float)last_height;
1276 OGL_ENABLE(TEXTURE_2D);
1279 ogl_pal=gr_current_pal;
1280 ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags, 0);
1283 OGL_BINDTEXTURE(tex.handle);
1285 ogl_texwrap(&tex,GL_CLAMP);
1288 glColor3f(1.0,1.0,1.0);
1289 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1290 glTexCoord2f(tex.u, v1); glVertex2f(xo+xs, yo);
1291 glTexCoord2f(tex.u, tex.v); glVertex2f(xo+xs, yo-ys);
1292 glTexCoord2f(u1, tex.v); glVertex2f(xo, yo-ys);
1294 ogl_freetexture(&tex);
1297 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1298 return ogl_ubitblt_i(w,h,dx,dy,w,h,sx,sy,src,dest);
1301 bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1303 unsigned char *d,*s;
1307 w1=grd_curscreen->sc_w;h1=grd_curscreen->sc_h;
1308 if (w1*h1*3>OGLTEXBUFSIZE)
1309 Error("ogl_ubitblt_tolinear: screen res larger than OGLTEXBUFSIZE\n");
1311 if (ogl_readpixels_ok>0){
1312 OGL_DISABLE(TEXTURE_2D);
1313 glReadBuffer(GL_FRONT);
1314 glReadPixels(0,0,w1,h1,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1315 // glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1316 // glReadPixels(sx,sy,w+sx,h+sy,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1318 memset(texbuf,0,w1*h1*3);
1322 d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1323 s=texbuf+((h1-(i+sy+1))*w1+sx)*3;
1325 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1332 unsigned char *d,*s,*e;
1333 if (w*h*3>OGLTEXBUFSIZE)
1334 Error("ogl_ubitblt_tolinear: size larger than OGLTEXBUFSIZE\n");
1337 #if 1//also seems to cause a mess. need to look into it a bit more..
1338 if (ogl_readpixels_ok>0){
1339 OGL_DISABLE(TEXTURE_2D);
1340 glReadBuffer(GL_FRONT);
1341 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1342 glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1345 memset(texbuf,0,w*h*3);
1346 // d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1347 d=dest->bm_data+dx+dy*dest->bm_rowsize;
1349 s=texbuf+w*(h-(i+1))*3;
1351 if (s<texbuf){Error("blah1\n");}
1352 if (d<dest->bm_data){Error("blah3\n");}
1353 // d=dest->bm_data+(i*dest->bm_rowsize);
1357 if (s>texbuf+w*h*3-3){Error("blah2\n");}
1358 if (d>dest->bm_data+dest->bm_rowsize*(h+dy)+dx ){Error("blah4\n");}
1359 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1365 d+=dest->bm_rowsize;
1367 glmprintf((0,"c=%i w*h=%i\n",c,w*h));
1372 bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1373 #if 0 //just seems to cause a mess.
1374 GLfloat xo,yo;//,xs,ys;
1379 // xo=dx/(float)last_width;
1380 xo=dx/(float)grd_curscreen->sc_w;
1381 // yo=1.0-(dy+h)/(float)last_height;
1382 yo=1.0-(dy+h)/(float)grd_curscreen->sc_h;
1385 OGL_DISABLE(TEXTURE_2D);
1386 glReadBuffer(GL_FRONT);
1387 glRasterPos2f(xo,yo);
1388 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1389 glCopyPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_COLOR);
1395 grs_canvas *offscreen_save_canv = NULL, *offscreen_canv = NULL;
1397 void ogl_start_offscreen_render(int x, int y, int w, int h)
1400 Error("ogl_start_offscreen_render: offscreen_canv!=NULL");
1401 offscreen_save_canv = grd_curcanv;
1402 offscreen_canv = gr_create_sub_canvas(grd_curcanv, x, y, w, h);
1403 gr_set_current_canvas(offscreen_canv);
1404 glDrawBuffer(GL_BACK);
1406 void ogl_end_offscreen_render(void)
1410 if (!offscreen_canv)
1411 Error("ogl_end_offscreen_render: no offscreen_canv");
1413 glDrawBuffer(GL_FRONT);
1414 glReadBuffer(GL_BACK);
1415 OGL_DISABLE(TEXTURE_2D);
1417 y = last_height - offscreen_canv->cv_bitmap.bm_y - offscreen_canv->cv_bitmap.bm_h;
1418 glRasterPos2f(offscreen_canv->cv_bitmap.bm_x/(float)last_width, y/(float)last_height);
1419 glCopyPixels(offscreen_canv->cv_bitmap.bm_x, y,
1420 offscreen_canv->cv_bitmap.bm_w,
1421 offscreen_canv->cv_bitmap.bm_h, GL_COLOR);
1423 gr_free_sub_canvas(offscreen_canv);
1424 gr_set_current_canvas(offscreen_save_canv);
1425 offscreen_canv=NULL;
1428 void ogl_start_frame(void){
1429 r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;
1430 // gl_badtexture=500;
1432 OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);
1433 glClearColor(0.0, 0.0, 0.0, 0.0);
1434 // glEnable(GL_ALPHA_TEST);
1435 // glAlphaFunc(GL_GREATER,0.01);
1436 glShadeModel(GL_SMOOTH);
1437 glMatrixMode(GL_PROJECTION);
1438 glLoadIdentity();//clear matrix
1439 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1440 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),0.01,1000000.0);
1441 gluPerspective(90.0,1.0,0.01,1000000.0);
1442 //gluPerspective(90.0,(GLfloat)(Canvas_width*3)/(GLfloat)(Canvas_height*4),0.01,1000000.0);
1443 // gluPerspective(75.0,(GLfloat)Canvas_width/(GLfloat)Canvas_height,1.0,1000000.0);
1444 glMatrixMode(GL_MODELVIEW);
1445 glLoadIdentity();//clear matrix
1447 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1448 // glDisABLE(DITHER);
1449 // glScalef(1.0,1.0,-1.0);
1450 // glScalef(1.0,1.0,-1.0);
1453 // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1454 // OGL_TEXENV(GL_TEXTURE_ENV_MODE,GL_MODULATE);
1455 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1456 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1457 // OGL_TEXPARAM(GL_TEXTURE_MAG_FILTER,GL_texmagfilt);
1458 // OGL_TEXPARAM(GL_TEXTURE_MIN_FILTER,GL_texminfilt);
1459 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1460 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1463 void merge_textures_stats(void);
1465 void ogl_end_frame(void){
1466 // OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);
1467 OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1469 // merge_textures_stats();
1470 // ogl_texture_stats();
1472 // glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1473 glMatrixMode(GL_PROJECTION);
1474 glLoadIdentity();//clear matrix
1475 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
1476 glMatrixMode(GL_MODELVIEW);
1477 glLoadIdentity();//clear matrix
1478 // glDisABLE(BLEND);
1479 //glDisABLE(ALPHA_TEST);
1480 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1481 // ogl_swap_buffers();//platform specific code
1482 // glClear(GL_COLOR_BUFFER_BIT);
1484 void ogl_swap_buffers(void){
1485 ogl_clean_texture_cache();
1486 if (gr_renderstats){
1487 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);
1488 // 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
1491 ogl_swap_buffers_internal();
1492 glClear(GL_COLOR_BUFFER_BIT);
1495 void ogl_init_shared_palette(void)
1497 #ifdef GL_EXT_paletted_texture
1498 if (ogl_shared_palette_ok)
1502 glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1503 //glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, ogl_pal);
1505 for (i = 0; i < 256; i++)
1509 texbuf[i * 4] = 255;
1510 texbuf[i * 4 + 1] = 255;
1511 texbuf[i * 4 + 2] = 255;
1512 texbuf[i * 4 + 3] = 0;
1517 texbuf[i * 4 + 1] = 0;
1518 texbuf[i * 4 + 2] = 0;
1519 texbuf[i * 4 + 3] = 0;
1523 texbuf[i * 4] = gr_current_pal[i * 3] * 4;
1524 texbuf[i * 4 + 1] = gr_current_pal[i * 3 + 1] * 4;
1525 texbuf[i * 4 + 2] = gr_current_pal[i * 3 + 2] * 4;
1526 texbuf[i * 4 + 3] = 255;
1529 glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
1534 int tex_format_supported(int iformat,int format){
1537 if (!ogl_intensity4_ok) return 0; break;
1538 case GL_LUMINANCE4_ALPHA4:
1539 if (!ogl_luminance4_alpha4_ok) return 0; break;
1541 if (!ogl_rgba2_ok) return 0; break;
1543 if (ogl_gettexlevelparam_ok){
1544 GLint internalFormat;
1545 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, iformat, 64, 64, 0,
1546 format, GL_UNSIGNED_BYTE, texbuf);//NULL?
1547 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
1548 GL_TEXTURE_INTERNAL_FORMAT,
1550 return (internalFormat==iformat);
1555 //little hack to find the largest or equal multiple of 2 for a given number
1559 for (i = 1; i <= 4096; i *= 2)
1564 //GLubyte texbuf[512*512*4];
1565 GLubyte texbuf[OGLTEXBUFSIZE];
1567 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)
1569 // GLushort *tex=(GLushort *)texp;
1571 if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
1572 Error("texture toobig %i %i",twidth,theight);
1575 for (y=0;y<theight;y++){
1576 i=dxo+truewidth*(y+dyo);
1577 for (x=0;x<twidth;x++){
1578 if (x<width && y<height)
1583 for (j = 0; j < data_format; ++j)
1584 (*(texp++)) = data[i * data_format + j];
1591 c = 256; // fill the pad space with transparency (or blackness)
1592 if (c == 254 && (bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1596 case GL_LUMINANCE_ALPHA:
1604 (*(texp++)) = 0; // transparent pixel
1606 case GL_COLOR_INDEX:
1610 Error("ogl_filltexbuf unhandled super-transparent texformat\n");
1614 else if ((c == 255 && (bm_flags & BM_FLAG_TRANSPARENT)) || c == 256)
1620 case GL_LUMINANCE_ALPHA:
1633 (*(texp++))=0;//transparent pixel
1635 case GL_COLOR_INDEX:
1639 Error("ogl_filltexbuf unknown texformat\n");
1644 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. :)
1647 case GL_LUMINANCE_ALPHA:
1652 (*(texp++)) = ogl_pal[c * 3] * 4;
1653 (*(texp++)) = ogl_pal[c * 3 + 1] * 4;
1654 (*(texp++)) = ogl_pal[c * 3 + 2] * 4;
1657 //(*(texp++))=gr_palette[c*3]*4;
1658 //(*(texp++))=gr_palette[c*3+1]*4;
1659 //(*(texp++))=gr_palette[c*3+2]*4;
1660 (*(texp++))=ogl_pal[c*3]*4;
1661 (*(texp++))=ogl_pal[c*3+1]*4;
1662 (*(texp++))=ogl_pal[c*3+2]*4;
1663 (*(texp++))=255;//not transparent
1664 // (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
1666 case GL_COLOR_INDEX:
1670 Error("ogl_filltexbuf unknown texformat\n");
1677 int tex_format_verify(ogl_texture *tex){
1678 while (!tex_format_supported(tex->internalformat,tex->format)){
1679 glmprintf((0,"tex format %x not supported",tex->internalformat));
1680 switch (tex->internalformat){
1682 if (ogl_luminance4_alpha4_ok){
1683 tex->internalformat=GL_LUMINANCE4_ALPHA4;
1684 tex->format=GL_LUMINANCE_ALPHA;
1686 }//note how it will fall through here if the statement is false
1687 case GL_LUMINANCE4_ALPHA4:
1689 tex->internalformat=GL_RGBA2;
1690 tex->format=GL_RGBA;
1692 }//note how it will fall through here if the statement is false
1694 tex->internalformat = ogl_rgba_internalformat;
1695 tex->format=GL_RGBA;
1698 mprintf((0,"...no tex format to fall back on\n"));
1701 glmprintf((0,"...falling back to %x\n",tex->internalformat));
1705 void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){
1707 if (tex->tw!=w || tex->th!=h){
1708 u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h);
1709 glmprintf((0,"shrunken texture?\n"));
1712 if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
1713 tex->bytes=((float)w*h*dbits)/8.0;
1714 tex->bytesu=((float)u*dbits)/8.0;
1716 tex->bytes=((float)w*h*bits)/8.0;
1717 tex->bytesu=((float)u*bits)/8.0;
1719 glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes));
1721 void tex_set_size(ogl_texture *tex){
1724 if (ogl_gettexlevelparam_ok){
1726 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w);
1727 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h);
1728 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t;
1729 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t;
1730 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t;
1731 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t;
1732 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t;
1733 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t;
1734 #ifdef GL_EXT_paletted_texture
1735 if (ogl_paletted_texture_ok)
1737 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INDEX_SIZE_EXT, &t);
1745 switch (tex->format){
1749 case GL_LUMINANCE_ALPHA:
1756 case GL_COLOR_INDEX:
1760 Error("tex_set_size unknown texformat\n");
1763 tex_set_size1(tex,bi,a,w,h);
1765 //loads a palettized bitmap into a ogl RGBA texture.
1766 //Sizes and pads dimensions to multiples of 2 if necessary.
1767 //In theory this could be a problem for repeating textures, but all real
1768 //textures (not sprites, etc) in descent are 64x64, so we are ok.
1769 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
1770 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format)
1772 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
1773 // int internalformat=GL_RGBA;
1774 // int format=GL_RGBA;
1776 tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
1777 // tex->tw=tex->w;tex->th=tex->h;//feeling lucky?
1779 if(gr_badtexture>0) return;
1781 #if !(defined(__APPLE__) && defined(__MACH__))
1782 // always fails on OS X, but textures work fine!
1783 if (tex_format_verify(tex))
1787 //calculate u/v values that would make the resulting texture correctly sized
1788 tex->u=(float)tex->w/(float)tex->tw;
1789 tex->v=(float)tex->h/(float)tex->th;
1791 #ifdef GL_EXT_paletted_texture
1792 if (ogl_shared_palette_ok && data_format == 0 && (tex->format == GL_RGBA || tex->format == GL_RGB) &&
1793 !(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.
1796 // descent makes palette entries 254 and 255 both do double duty, depending upon the setting of BM_FLAG_SUPER_TRANSPARENT and BM_FLAG_TRANSPARENT.
1797 // 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.)
1798 // We don't handle super transparent textures with ogl yet, so we don't bother checking that here.
1799 int usesthetransparentindexcolor = 0, usesthesupertransparentindexcolor = 0;
1801 if (!(bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1805 for (i = 0; i < tex->w * tex->h; ++i)
1807 usesthesupertransparentindexcolor += 1;
1809 if (!(bm_flags & BM_FLAG_TRANSPARENT))
1813 for (i=0; i < tex->w * tex->h; ++i)
1815 usesthetransparentindexcolor += 1;
1817 if (!usesthetransparentindexcolor && !usesthesupertransparentindexcolor)
1819 tex->internalformat = GL_COLOR_INDEX8_EXT;
1820 tex->format = GL_COLOR_INDEX;
1823 // printf("bm data=%p w=%i h=%i transparent:%i supertrans:%i\n", data, tex->w, tex->h, usesthetransparentindexcolor, usesthesupertransparentindexcolor);
1827 // if (width!=twidth || height!=theight)
1828 // glmprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
1829 ogl_filltexbuf(data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags, data_format);
1831 // Generate OpenGL texture IDs.
1832 glGenTextures(1, &tex->handle);
1835 glPrioritizeTextures(1,&tex->handle,&tex->prio);
1837 // Give our data to OpenGL.
1839 OGL_BINDTEXTURE(tex->handle);
1841 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1844 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1845 if (ogl_ext_texture_filter_anisotropic_ok && GL_texanisofilt)
1846 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_texanisofilt);
1850 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1851 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1853 // domipmap=0;//mipmaps aren't used in GL_NEAREST anyway, and making the mipmaps is pretty slow
1854 //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.
1856 if (tex->wantmip && GL_needmipmaps)
1857 gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
1858 tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
1860 glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
1861 tex->tw, tex->th, 0, tex->format, // RGBA textures.
1862 GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
1868 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));
1872 unsigned char decodebuf[512*512];
1874 void ogl_loadbmtexture_f(grs_bitmap *bm, int flags)
1881 while (bm->bm_parent)
1883 if (bm->gltexture && bm->gltexture->handle > 0)
1887 if ((bitmapname = piggy_game_bitmap_name(bm)))
1892 sprintf(filename, "textures/%s.png", bitmapname);
1893 if (read_png(filename, &pdata))
1895 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);
1896 if (pdata.depth == 8 && pdata.color)
1898 if (bm->gltexture == NULL)
1899 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));
1900 ogl_loadtexture(pdata.data, 0, 0, bm->gltexture, bm->bm_flags, pdata.paletted ? 0 : pdata.channels);
1903 free(pdata.palette);
1908 printf("%s: unsupported texture format: must be rgb, rgba, or paletted, and depth 8\n", filename);
1911 free(pdata.palette);
1916 if (bm->gltexture == NULL){
1917 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));
1920 if (bm->gltexture->handle>0)
1922 if (bm->gltexture->w==0){
1923 bm->gltexture->lw=bm->bm_w;
1924 bm->gltexture->w=bm->bm_w;
1925 bm->gltexture->h=bm->bm_h;
1928 if (bm->bm_flags & BM_FLAG_RLE){
1929 unsigned char * dbits;
1930 unsigned char * sbits;
1934 if (bm->bm_flags & BM_FLAG_RLE_BIG)
1937 sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)];
1940 for (i=0; i < bm->bm_h; i++ ) {
1941 gr_rle_decode(sbits,dbits);
1942 if ( bm->bm_flags & BM_FLAG_RLE_BIG )
1943 sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)])));
1945 sbits += (int)bm->bm_data[4+i];
1950 ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags, 0);
1953 void ogl_loadbmtexture(grs_bitmap *bm)
1955 ogl_loadbmtexture_f(bm, OGL_FLAG_MIPMAP);
1958 void ogl_freetexture(ogl_texture *gltexture)
1960 if (gltexture->handle>0) {
1962 glmprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
1963 glDeleteTextures( 1, &gltexture->handle );
1964 // gltexture->handle=0;
1965 ogl_reset_texture(gltexture);
1968 void ogl_freebmtexture(grs_bitmap *bm){
1970 ogl_freetexture(bm->gltexture);
1973 // glmprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
1974 // glDeleteTextures( 1, &bm->gltexture );
1975 // bm->gltexture=-1;