1 /* $Id: ogl.c,v 1.34 2004-08-01 13:01:39 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 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 GLint idx, r, g, b, a, dbl, depth;
286 int res, colorsize, depthsize;
288 res = SWIDTH * SHEIGHT;
289 glGetIntegerv(GL_INDEX_BITS, &idx);
290 glGetIntegerv(GL_RED_BITS, &r);
291 glGetIntegerv(GL_GREEN_BITS, &g);
292 glGetIntegerv(GL_BLUE_BITS, &b);
293 glGetIntegerv(GL_ALPHA_BITS, &a);
294 glGetIntegerv(GL_DOUBLEBUFFER, &dbl);
296 glGetIntegerv(GL_DEPTH_BITS, &depth);
297 colorsize = (idx * res * dbl) / 8;
298 depthsize = res * depth / 8;
299 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);
300 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);
301 gr_printf(5, GAME_FONT->ft_h * 16 + 3 * 16, "total=%iK", (colorsize + depthsize + truebytes) / 1024);
303 // 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));
306 int ogl_mem_target=-1;
307 void ogl_clean_texture_cache(void){
312 if (ogl_mem_target<0){
318 bytes=ogl_texture_stats();
319 while (bytes>ogl_mem_target){
320 for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
321 t=&ogl_texture_list[i];
323 if (t->lastrend+f1_0*time<GameTime){
326 if (bytes<ogl_mem_target)
332 Error("not enough mem?");
337 void ogl_bindbmtex(grs_bitmap *bm){
338 if (bm->gltexture==NULL || bm->gltexture->handle<=0)
339 ogl_loadbmtexture(bm);
340 OGL_BINDTEXTURE(bm->gltexture->handle);
341 bm->gltexture->lastrend=GameTime;
342 bm->gltexture->numrend++;
343 //// if (bm->gltexture->numrend==80 || bm->gltexture->numrend==4000 || bm->gltexture->numrend==80000){
344 // if (bm->gltexture->numrend==100){
345 // bm->gltexture->prio+=0.1;
346 //// glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY,bm->gltexture->prio);
347 // glPrioritizeTextures(1,&bm->gltexture->handle,&bm->gltexture->prio);
350 //gltexture MUST be bound first
351 void ogl_texwrap(ogl_texture *gltexture,int state)
353 if (gltexture->wrapstate[active_texture_unit] != state || gltexture->numrend < 1)
355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state);
356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state);
357 gltexture->wrapstate[active_texture_unit] = state;
361 //crude texture precaching
362 //handles: powerups, walls, weapons, polymodels, etc.
363 //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.
364 //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
367 void ogl_cache_polymodel_textures(int model_num)
374 po = &Polygon_models[model_num];
375 for (i=0;i<po->n_textures;i++) {
376 // texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]];
377 ogl_loadbmtexture(&GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]);
380 void ogl_cache_vclip_textures(vclip *vc){
382 for (i=0;i<vc->num_frames;i++){
383 PIGGY_PAGE_IN(vc->frames[i]);
384 ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]);
388 void ogl_cache_vclipn_textures(int i)
390 if (i >= 0 && i < VCLIP_MAXNUM)
391 ogl_cache_vclip_textures(&Vclip[i]);
394 void ogl_cache_weapon_textures(int weapon_type)
400 w = &Weapon_info[weapon_type];
401 ogl_cache_vclipn_textures(w->flash_vclip);
402 ogl_cache_vclipn_textures(w->robot_hit_vclip);
403 ogl_cache_vclipn_textures(w->wall_hit_vclip);
404 if (w->render_type==WEAPON_RENDER_VCLIP)
405 ogl_cache_vclipn_textures(w->weapon_vclip);
406 else if (w->render_type == WEAPON_RENDER_POLYMODEL)
408 ogl_cache_polymodel_textures(w->model_num);
409 ogl_cache_polymodel_textures(w->model_num_inner);
413 void ogl_cache_level_textures(void)
422 ogl_reset_texture_stats_internal();//loading a new lev should reset textures
424 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
425 ogl_cache_vclipn_textures(Effects[i].dest_vclip);
426 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
428 if (ec->vc.num_frames>max_efx)
429 max_efx=ec->vc.num_frames;
431 glmprintf((0,"max_efx:%i\n",max_efx));
432 for (ef=0;ef<max_efx;ef++){
433 for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
434 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
436 // if (ec->vc.num_frames>max_efx)
437 // max_efx=ec->vc.num_frames;
440 do_special_effects();
442 for (seg=0;seg<Num_segments;seg++){
443 for (side=0;side<MAX_SIDES_PER_SEGMENT;side++){
444 sidep=&Segments[seg].sides[side];
445 tmap1=sidep->tmap_num;
446 tmap2=sidep->tmap_num2;
447 if (tmap1<0 || tmap1>=NumTextures){
448 glmprintf((0,"ogl_cache_level_textures %i %i %i %i\n",seg,side,tmap1,NumTextures));
452 PIGGY_PAGE_IN(Textures[tmap1]);
453 bm = &GameBitmaps[Textures[tmap1].index];
455 PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]);
456 bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index];
457 if (ogl_alttexmerge == 0 || (!OGL_SUPER_TRANSPARENT_OK && (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT)))
458 bm = texmerge_get_cached_bitmap( tmap1, tmap2 );
460 ogl_loadbmtexture(bm2);
462 // 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));
464 ogl_loadbmtexture(bm);
467 glmprintf((0,"finished ef:%i\n",ef));
469 reset_special_effects();
470 init_special_effects();
474 // always have lasers, concs, flares. Always shows player appearance, and at least concs are always available to disappear.
475 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
476 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
477 ogl_cache_weapon_textures(FLARE_ID);
478 ogl_cache_vclipn_textures(VCLIP_PLAYER_APPEARANCE);
479 ogl_cache_vclipn_textures(VCLIP_POWERUP_DISAPPEARANCE);
480 ogl_cache_polymodel_textures(Player_ship->model_num);
481 ogl_cache_vclipn_textures(Player_ship->expl_vclip_num);
483 for (i=0;i<Highest_object_index;i++){
484 if(Objects[i].render_type==RT_POWERUP){
485 ogl_cache_vclipn_textures(Objects[i].rtype.vclip_info.vclip_num);
486 switch (Objects[i].id){
488 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]);
492 case POW_VULCAN_WEAPON:
493 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]);
495 case POW_SPREADFIRE_WEAPON:
496 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]);
498 case POW_PLASMA_WEAPON:
499 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]);
501 case POW_FUSION_WEAPON:
502 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]);
504 /* case POW_MISSILE_1:
506 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]);
508 case POW_PROXIMITY_WEAPON:
509 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]);
511 case POW_HOMING_AMMO_1:
512 case POW_HOMING_AMMO_4:
513 ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]);
515 case POW_SMARTBOMB_WEAPON:
516 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]);
518 case POW_MEGA_WEAPON:
519 ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]);
523 else if(Objects[i].render_type==RT_POLYOBJ){
524 //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);
525 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp1_vclip_num);
526 ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp2_vclip_num);
527 ogl_cache_weapon_textures(Robot_info[Objects[i].id].weapon_type);
528 ogl_cache_polymodel_textures(Objects[i].rtype.pobj_info.model_num);
532 glmprintf((0,"finished caching\n"));
533 r_cachedtexcount = r_texcount;
536 int r_polyc,r_tpolyc,r_bitmapc,r_ubitmapc,r_ubitbltc,r_upixelc;
537 #define f2glf(x) (f2fl(x))
539 bool g3_draw_line(g3s_point *p0,g3s_point *p1)
542 c=grd_curcanv->cv_color;
543 OGL_DISABLE(TEXTURE_2D);
544 glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
546 glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));
547 glVertex3f(f2glf(p1->p3_vec.x),f2glf(p1->p3_vec.y),-f2glf(p1->p3_vec.z));
551 void ogl_drawcircle2(int nsides,int type,float xsc,float xo,float ysc,float yo){
555 for (i=0; i<nsides; i++) {
556 ang = 2.0*M_PI*i/nsides;
557 glVertex2f(cosf(ang)*xsc+xo,sinf(ang)*ysc+yo);
561 void ogl_drawcircle(int nsides,int type){
565 for (i=0; i<nsides; i++) {
566 ang = 2.0*M_PI*i/nsides;
567 glVertex2f(cosf(ang),sinf(ang));
571 int circle_list_init(int nsides,int type,int mode) {
572 int hand=glGenLists(1);
573 glNewList(hand, mode);
574 /* draw a unit radius circle in xy plane centered on origin */
575 ogl_drawcircle(nsides,type);
579 float bright_g[4]={ 32.0/256, 252.0/256, 32.0/256};
580 float dark_g[4]={ 32.0/256, 148.0/256, 32.0/256};
581 float darker_g[4]={ 32.0/256, 128.0/256, 32.0/256};
582 void ogl_draw_reticle(int cross,int primary,int secondary){
583 float scale=(float)Canvas_height/(float)grd_curscreen->sc_h;
585 // glTranslatef(0.5,0.5,0);
586 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);
587 glScalef(scale/320.0,scale/200.0,scale);//the positions are based upon the standard reticle at 320x200 res.
589 OGL_DISABLE(TEXTURE_2D);
591 if (!cross_lh[cross]){
592 cross_lh[cross]=glGenLists(1);
593 glNewList(cross_lh[cross], GL_COMPILE_AND_EXECUTE);
596 glColor3fv(darker_g);
597 glVertex2f(-4.0,4.0);
599 glColor3fv(bright_g);
602 glVertex2f(-2.0,2.0);
606 glVertex2f(-3.0,-2.0);
608 glColor3fv(bright_g);
609 glVertex2f(-2.0,-1.0);
612 glColor3fv(darker_g);
615 glColor3fv(bright_g);
622 glVertex2f(3.0,-2.0);
624 glColor3fv(bright_g);
625 glVertex2f(2.0,-1.0);
630 glCallList(cross_lh[cross]);
632 // if (Canvas_height>200)
633 // glLineWidth(Canvas_height/(float)200);
634 if (!primary_lh[primary]){
635 primary_lh[primary]=glGenLists(1);
636 glNewList(primary_lh[primary], GL_COMPILE_AND_EXECUTE);
641 glVertex2f(-14.0,-8.0);
642 glVertex2f(-8.0,-5.0);
644 glVertex2f(14.0,-8.0);
645 glVertex2f(8.0,-5.0);
650 glColor3fv(bright_g);
652 ogl_drawcircle2(6,GL_POLYGON,1.5,-7.0,1.5,-5.0);
654 ogl_drawcircle2(6,GL_POLYGON,1.5,7.0,1.5,-5.0);
658 glColor3fv(bright_g);
660 ogl_drawcircle2(4,GL_POLYGON,1.0,-14.0,1.0,-8.0);
662 ogl_drawcircle2(4,GL_POLYGON,1.0,14.0,1.0,-8.0);
666 glCallList(primary_lh[primary]);
667 // if (Canvas_height>200)
670 if (!secondary_lh[secondary]){
671 secondary_lh[secondary]=glGenLists(1);
672 glNewList(secondary_lh[secondary], GL_COMPILE_AND_EXECUTE);
676 glColor3fv(darker_g);
678 glColor3fv(bright_g);
679 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,-10.0,2.0,-1.0);
682 glColor3fv(darker_g);
684 glColor3fv(bright_g);
685 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,10.0,2.0,-1.0);
687 //bottom/middle secondary
689 glColor3fv(darker_g);
691 glColor3fv(bright_g);
692 ogl_drawcircle2(8,GL_LINE_LOOP,2.0,0.0,2.0,-7.0);
696 glCallList(secondary_lh[secondary]);
700 int g3_draw_sphere(g3s_point *pnt,fix rad){
702 c=grd_curcanv->cv_color;
703 OGL_DISABLE(TEXTURE_2D);
704 // glPointSize(f2glf(rad));
705 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
706 // glBegin(GL_POINTS);
707 // glVertex3f(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
710 glTranslatef(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z));
711 glScalef(f2glf(rad),f2glf(rad),f2glf(rad));
712 if (!sphereh) sphereh=circle_list_init(20,GL_POLYGON,GL_COMPILE_AND_EXECUTE);
713 else glCallList(sphereh);
718 int gr_ucircle(fix xc1, fix yc1, fix r1)
721 c=grd_curcanv->cv_color;
722 OGL_DISABLE(TEXTURE_2D);
723 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
726 (f2fl(xc1) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width,
727 1.0 - (f2fl(yc1) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0);
728 glScalef(f2fl(r1) / last_width, f2fl(r1) / last_height, 1.0);
729 ogl_drawcircle(10 + 2 * (int)(M_PI * f2fl(r1) / 19), GL_LINE_LOOP);
733 int gr_circle(fix xc1,fix yc1,fix r1){
734 return gr_ucircle(xc1,yc1,r1);
737 bool g3_draw_poly(int nv,g3s_point **pointlist)
741 c=grd_curcanv->cv_color;
742 // 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);
743 OGL_DISABLE(TEXTURE_2D);
744 if (Gr_scanline_darkening_level >= GR_FADE_LEVELS)
745 glColor3f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c));
747 glColor4f(PAL2Tr(c), PAL2Tg(c), PAL2Tb(c), 1.0 - (float)Gr_scanline_darkening_level / ((float)GR_FADE_LEVELS - 1.0));
748 glBegin(GL_TRIANGLE_FAN);
750 // glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
751 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
757 void gr_upoly_tmap(int nverts, int *vert ){
758 mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
760 void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){
761 mprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called
763 extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist);
764 bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)
768 if (tmap_drawer_ptr==draw_tmap_flat){
769 /* fix average_light=0;
772 average_light += uvl_list[i].l;*/
773 OGL_DISABLE(TEXTURE_2D);
774 // glmprintf((0,"Gr_scanline_darkening_level=%i %f\n",Gr_scanline_darkening_level,Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
775 glColor4f(0,0,0,1.0-(Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
776 //glColor4f(0,0,0,f2fl(average_light/nv));
777 glBegin(GL_TRIANGLE_FAN);
779 // glColor4f(0,0,0,f2fl(uvl_list[c].l));
780 // glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
781 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
784 }else if (tmap_drawer_ptr==draw_tmap){
786 /* if (bm->bm_w !=64||bm->bm_h!=64)
787 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
788 OGL_ENABLE(TEXTURE_2D);
790 ogl_texwrap(bm->gltexture,GL_REPEAT);
791 glBegin(GL_TRIANGLE_FAN);
793 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
796 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
797 l=f2fl(uvl_list[c].l);
800 glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
801 //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
802 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
806 mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
811 int active_texture_unit = 0;
813 void ogl_setActiveTexture(int t)
815 if (ogl_arb_multitexture_ok)
817 #ifdef GL_ARB_multitexture
819 glActiveTextureARB(GL_TEXTURE0_ARB);
821 glActiveTextureARB(GL_TEXTURE1_ARB);
824 else if (ogl_sgis_multitexture_ok)
826 #ifdef GL_SGIS_multitexture
828 glSelectTextureSGIS(GL_TEXTURE0_SGIS);
830 glSelectTextureSGIS(GL_TEXTURE1_SGIS);
833 active_texture_unit = t;
836 void ogl_MultiTexCoord2f(int t, float u, float v)
838 if (ogl_arb_multitexture_ok)
840 #ifdef GL_ARB_multitexture
842 glMultiTexCoord2fARB(GL_TEXTURE0_ARB, u, v);
844 glMultiTexCoord2fARB(GL_TEXTURE1_ARB, u, v);
847 else if (ogl_sgis_multitexture_ok)
849 #ifdef GL_SGIS_multitexture
851 glMultiTexCoord2fSGIS(GL_TEXTURE0_SGIS, u, v);
853 glMultiTexCoord2fSGIS(GL_TEXTURE1_SGIS, u, v);
858 bool g3_draw_tmap_2(int nv, g3s_point **pointlist, g3s_uvl *uvl_list, grs_bitmap *bmbot, grs_bitmap *bm, int orient)
860 #if ((defined(GL_NV_register_combiners) || defined(GL_NV_texture_env_combine4)) && (defined(GL_ARB_multitexture) || defined(GL_SGIS_multitexture)))
861 if ((/*ogl_nv_register_combiners_ok ||*/ ogl_nv_texture_env_combine4_ok) && (ogl_arb_multitexture_ok || ogl_sgis_multitexture_ok))
866 if (tmap_drawer_ptr != draw_tmap)
871 //ogl_setActiveTexture(0);
872 OGL_ENABLE(TEXTURE_2D);
873 ogl_bindbmtex(bmbot);
874 ogl_texwrap(bmbot->gltexture, GL_REPEAT);
875 // GL_MODULATE is fine for texture 0
877 ogl_setActiveTexture(1);
878 glEnable(GL_TEXTURE_2D);
880 ogl_texwrap(bm->gltexture,GL_REPEAT);
882 #ifdef GL_NV_register_combiners
883 if (ogl_nv_register_combiners_ok)
885 glEnable(GL_REGISTER_COMBINERS_NV);
886 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 1);
887 // spare0 = tex0 * (1-alpha1) + tex1 * alpha1
888 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
889 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
890 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
891 glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
893 GL_COMBINER0_NV, //GLenum stage
894 GL_RGB, //GLenum portion,
895 GL_DISCARD_NV, //GLenum abOutput,
896 GL_DISCARD_NV, //GLenum cdOutput,
897 GL_SPARE0_NV, //GLenum sumOutput,
898 GL_NONE, //GLenum scale,
899 GL_NONE, //GLenum bias,
900 GL_FALSE, //GLboolean abDotProduct,
901 GL_FALSE, //GLboolean cdDotProduct,
902 GL_FALSE //GLboolean muxSum
904 // out = spare0 * color
905 // ( out = AB + (1-A)C + D )
906 glFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
907 glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
908 glFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
909 glFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
911 if (bm->bm_flags & BM_FLAG_SUPER_TRANSPARENT)
913 // out = alpha0*(1-tex1) + alpha1
914 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
915 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_INVERT_NV, GL_BLUE);
916 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
917 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
921 // out = alpha0 + alpha1
922 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_A_NV, GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
923 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_B_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
924 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_C_NV, GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
925 glCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
928 GL_COMBINER0_NV, //GLenum stage
929 GL_ALPHA, //GLenum portion,
930 GL_DISCARD_NV, //GLenum abOutput,
931 GL_DISCARD_NV, //GLenum cdOutput,
932 GL_SPARE0_NV, //GLenum sumOutput,
933 GL_NONE, //GLenum scale,
934 GL_NONE, //GLenum bias,
935 GL_FALSE, //GLboolean abDotProduct,
936 GL_FALSE, //GLboolean cdDotProduct,
937 GL_FALSE //GLboolean muxSum
939 glFinalCombinerInputNV(GL_VARIABLE_G_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA);
944 //http://oss.sgi.com/projects/ogl-sample/registry/NV/texture_env_combine4.txt
945 //only GL_NV_texture_env_combine4 lets us do what we need:
946 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
948 //multiply top texture by color(vertex lighting) and add bottom texture(where alpha says to)
949 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
951 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
952 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT);
953 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE);
954 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS_EXT);
956 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
957 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
958 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_ONE_MINUS_SRC_ALPHA);
959 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR);
961 //add up alpha channels
962 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD);
964 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE);
965 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_ZERO);
966 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, GL_PREVIOUS_EXT);
967 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO);
969 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
970 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA);
971 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
972 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA);
975 // GL_DECAL works sorta ok but the top texture is fullbright.
976 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
978 // GL_ARB_texture_env_combine comes close, but doesn't quite make it.
979 //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
981 //// this gives effect like GL_DECAL:
982 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
983 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
984 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
985 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
988 // this properly shades the top texture, but the bottom texture doesn't get through.
989 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
990 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
991 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
995 //glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD);
996 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
997 //glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB);
999 glBegin(GL_TRIANGLE_FAN);
1003 u1=1.0-f2glf(uvl_list[c].v);
1004 v1=f2glf(uvl_list[c].u);
1007 u1=1.0-f2glf(uvl_list[c].u);
1008 v1=1.0-f2glf(uvl_list[c].v);
1011 u1=f2glf(uvl_list[c].v);
1012 v1=1.0-f2glf(uvl_list[c].u);
1015 u1=f2glf(uvl_list[c].u);
1016 v1=f2glf(uvl_list[c].v);
1019 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1022 l=f2fl(uvl_list[c].l);
1025 ogl_MultiTexCoord2f(0, f2glf(uvl_list[c].u), f2glf(uvl_list[c].v));
1026 ogl_MultiTexCoord2f(1, u1, v1);
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));
1029 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1032 //ogl_setActiveTexture(1); // still the active texture
1033 #ifdef GL_NV_register_combiners
1034 if (ogl_nv_register_combiners_ok)
1036 glDisable(GL_REGISTER_COMBINERS_NV);
1041 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1043 glDisable(GL_TEXTURE_2D);
1044 ogl_setActiveTexture(0);
1052 g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
1055 /* if (bm->bm_w !=64||bm->bm_h!=64)
1056 printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
1057 OGL_ENABLE(TEXTURE_2D);
1059 ogl_texwrap(bm->gltexture,GL_REPEAT);
1060 glBegin(GL_TRIANGLE_FAN);
1064 u1=1.0-f2glf(uvl_list[c].v);
1065 v1=f2glf(uvl_list[c].u);
1068 u1=1.0-f2glf(uvl_list[c].u);
1069 v1=1.0-f2glf(uvl_list[c].v);
1072 u1=f2glf(uvl_list[c].v);
1073 v1=1.0-f2glf(uvl_list[c].u);
1076 u1=f2glf(uvl_list[c].u);
1077 v1=f2glf(uvl_list[c].v);
1080 if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
1083 //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
1084 l=f2fl(uvl_list[c].l);
1087 glTexCoord2f(u1,v1);
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));
1090 glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
1097 bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm, int orientation)
1100 vms_vector pv,v1;//,v2;
1104 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1105 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1107 OGL_ENABLE(TEXTURE_2D);
1109 ogl_texwrap(bm->gltexture,GL_CLAMP);
1112 glColor3f(1.0,1.0,1.0);
1113 width = fixmul(width,Matrix_scale.x);
1114 height = fixmul(height,Matrix_scale.y);
1116 // g3_rotate_point(&p[i],pos);
1117 vm_vec_sub(&v1,pos,&View_position);
1118 vm_vec_rotate(&pv,&v1,&View_matrix);
1119 // printf(" %f,%f,%f->",f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1122 glTexCoord2f(0.0, 0.0);
1127 glTexCoord2f(bm->gltexture->u, 0.0);
1132 glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
1137 glTexCoord2f(0.0, bm->gltexture->v);
1142 // vm_vec_rotate(&v2,&v1,&View_matrix);
1143 // vm_vec_sub(&v1,&v2,&pv);
1144 //vm_vec_sub(&v1,&pv,&v2);
1145 // vm_vec_sub(&v2,&pv,&v1);
1146 glVertex3f(f2glf(pv.x),f2glf(pv.y),-f2glf(pv.z));
1147 // printf("%f,%f,%f ",f2glf(v1.x),f2glf(v1.y),-f2glf(v1.z));
1155 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
1157 GLfloat xo,yo,xf,yf;
1158 GLfloat u1,u2,v1,v2;
1160 x+=grd_curcanv->cv_bitmap.bm_x;
1161 y+=grd_curcanv->cv_bitmap.bm_y;
1162 xo=x/(float)last_width;
1163 xf=(bm->bm_w+x)/(float)last_width;
1164 yo=1.0-y/(float)last_height;
1165 yf=1.0-(bm->bm_h+y)/(float)last_height;
1167 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
1168 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
1170 /* glEnABLE(ALPHA_TEST);
1171 glAlphaFunc(GL_GREATER,0.0);*/
1173 OGL_ENABLE(TEXTURE_2D);
1175 ogl_texwrap(bm->gltexture,GL_CLAMP);
1179 if (bm->bm_w==bm->gltexture->w)
1180 u2=bm->gltexture->u;
1182 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1184 u1=bm->bm_x/(float)bm->gltexture->tw;
1185 u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
1189 if (bm->bm_h==bm->gltexture->h)
1190 v2=bm->gltexture->v;
1192 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1194 v1=bm->bm_y/(float)bm->gltexture->th;
1195 v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
1200 glColor3f(1.0,1.0,1.0);
1202 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
1203 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1204 glTexCoord2f(u2, v1); glVertex2f(xf, yo);
1205 glTexCoord2f(u2, v2); glVertex2f(xf, yf);
1206 glTexCoord2f(u1, v2); glVertex2f(xo, yf);
1208 // glDisABLE(ALPHA_TEST);
1212 bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){
1213 return ogl_ubitmapm_c(x,y,bm,-1);
1214 // return ogl_ubitblt(bm->bm_w,bm->bm_h,x,y,0,0,bm,NULL);
1217 //also upsidedown, currently.
1218 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1220 GLfloat xo,yo;//,xs,ys;
1221 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));
1226 xo=dx/(float)last_width;
1227 // xo=dx/(float)grd_curscreen->sc_w;
1228 // xs=w/(float)last_width;
1229 //yo=1.0-dy/(float)last_height;
1230 yo=1.0-(dy+h)/(float)last_height;
1231 // ys=h/(float)last_height;
1233 // OGL_ENABLE(TEXTURE_2D);
1235 OGL_DISABLE(TEXTURE_2D);
1236 glRasterPos2f(xo,yo);
1237 ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h,GL_RGBA);
1238 glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);
1244 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)
1246 GLfloat xo,yo,xs,ys;
1247 GLfloat u1,v1;//,u2,v2;
1249 // unsigned char *oldpal;
1252 ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA);
1254 tex.lw=src->bm_rowsize;
1256 /* if (w==src->bm_w && sx==0){
1259 u1=sx/(float)src->bm_w*src->glu;
1260 u2=w/(float)src->bm_w*src->glu+u1;
1262 if (h==src->bm_h && sy==0){
1265 v1=sy/(float)src->bm_h*src->glv;
1266 v2=h/(float)src->bm_h*src->glv+v1;
1272 xo=dx/(float)last_width;
1273 xs=dw/(float)last_width;
1274 yo=1.0-dy/(float)last_height;
1275 ys=dh/(float)last_height;
1277 OGL_ENABLE(TEXTURE_2D);
1280 ogl_pal=gr_current_pal;
1281 ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags, 0);
1284 OGL_BINDTEXTURE(tex.handle);
1286 ogl_texwrap(&tex,GL_CLAMP);
1289 glColor3f(1.0,1.0,1.0);
1290 glTexCoord2f(u1, v1); glVertex2f(xo, yo);
1291 glTexCoord2f(tex.u, v1); glVertex2f(xo+xs, yo);
1292 glTexCoord2f(tex.u, tex.v); glVertex2f(xo+xs, yo-ys);
1293 glTexCoord2f(u1, tex.v); glVertex2f(xo, yo-ys);
1295 ogl_freetexture(&tex);
1298 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1299 return ogl_ubitblt_i(w,h,dx,dy,w,h,sx,sy,src,dest);
1302 bool ogl_ubitblt_tolinear(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1304 unsigned char *d,*s;
1308 w1=grd_curscreen->sc_w;h1=grd_curscreen->sc_h;
1309 if (w1*h1*3>OGLTEXBUFSIZE)
1310 Error("ogl_ubitblt_tolinear: screen res larger than OGLTEXBUFSIZE\n");
1312 if (ogl_readpixels_ok>0){
1313 OGL_DISABLE(TEXTURE_2D);
1314 glReadBuffer(GL_FRONT);
1315 glReadPixels(0,0,w1,h1,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1316 // glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1317 // glReadPixels(sx,sy,w+sx,h+sy,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1319 memset(texbuf,0,w1*h1*3);
1323 d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1324 s=texbuf+((h1-(i+sy+1))*w1+sx)*3;
1326 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1333 unsigned char *d,*s,*e;
1334 if (w*h*3>OGLTEXBUFSIZE)
1335 Error("ogl_ubitblt_tolinear: size larger than OGLTEXBUFSIZE\n");
1338 #if 1//also seems to cause a mess. need to look into it a bit more..
1339 if (ogl_readpixels_ok>0){
1340 OGL_DISABLE(TEXTURE_2D);
1341 glReadBuffer(GL_FRONT);
1342 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1343 glReadPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1346 memset(texbuf,0,w*h*3);
1347 // d=dest->bm_data+dx+(dy+i)*dest->bm_rowsize;
1348 d=dest->bm_data+dx+dy*dest->bm_rowsize;
1350 s=texbuf+w*(h-(i+1))*3;
1352 if (s<texbuf){Error("blah1\n");}
1353 if (d<dest->bm_data){Error("blah3\n");}
1354 // d=dest->bm_data+(i*dest->bm_rowsize);
1358 if (s>texbuf+w*h*3-3){Error("blah2\n");}
1359 if (d>dest->bm_data+dest->bm_rowsize*(h+dy)+dx ){Error("blah4\n");}
1360 *d=gr_find_closest_color(s[0]/4,s[1]/4,s[2]/4);
1366 d+=dest->bm_rowsize;
1368 glmprintf((0,"c=%i w*h=%i\n",c,w*h));
1373 bool ogl_ubitblt_copy(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){
1374 #if 0 //just seems to cause a mess.
1375 GLfloat xo,yo;//,xs,ys;
1380 // xo=dx/(float)last_width;
1381 xo=dx/(float)grd_curscreen->sc_w;
1382 // yo=1.0-(dy+h)/(float)last_height;
1383 yo=1.0-(dy+h)/(float)grd_curscreen->sc_h;
1386 OGL_DISABLE(TEXTURE_2D);
1387 glReadBuffer(GL_FRONT);
1388 glRasterPos2f(xo,yo);
1389 // glReadPixels(0,0,w,h,GL_RGB,GL_UNSIGNED_BYTE,texbuf);
1390 glCopyPixels(sx,grd_curscreen->sc_h-(sy+h),w,h,GL_COLOR);
1396 grs_canvas *offscreen_save_canv = NULL, *offscreen_canv = NULL;
1398 void ogl_start_offscreen_render(int x, int y, int w, int h)
1401 Error("ogl_start_offscreen_render: offscreen_canv!=NULL");
1402 offscreen_save_canv = grd_curcanv;
1403 offscreen_canv = gr_create_sub_canvas(grd_curcanv, x, y, w, h);
1404 gr_set_current_canvas(offscreen_canv);
1405 glDrawBuffer(GL_BACK);
1407 void ogl_end_offscreen_render(void)
1411 if (!offscreen_canv)
1412 Error("ogl_end_offscreen_render: no offscreen_canv");
1414 glDrawBuffer(GL_FRONT);
1415 glReadBuffer(GL_BACK);
1416 OGL_DISABLE(TEXTURE_2D);
1418 y = last_height - offscreen_canv->cv_bitmap.bm_y - offscreen_canv->cv_bitmap.bm_h;
1419 glRasterPos2f(offscreen_canv->cv_bitmap.bm_x/(float)last_width, y/(float)last_height);
1420 glCopyPixels(offscreen_canv->cv_bitmap.bm_x, y,
1421 offscreen_canv->cv_bitmap.bm_w,
1422 offscreen_canv->cv_bitmap.bm_h, GL_COLOR);
1424 gr_free_sub_canvas(offscreen_canv);
1425 gr_set_current_canvas(offscreen_save_canv);
1426 offscreen_canv=NULL;
1429 void ogl_start_frame(void){
1430 r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;
1431 // gl_badtexture=500;
1433 OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);
1434 glClearColor(0.0, 0.0, 0.0, 0.0);
1435 // glEnable(GL_ALPHA_TEST);
1436 // glAlphaFunc(GL_GREATER,0.01);
1437 glShadeModel(GL_SMOOTH);
1438 glMatrixMode(GL_PROJECTION);
1439 glLoadIdentity();//clear matrix
1440 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1441 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),0.01,1000000.0);
1442 gluPerspective(90.0,1.0,0.01,1000000.0);
1443 //gluPerspective(90.0,(GLfloat)(Canvas_width*3)/(GLfloat)(Canvas_height*4),0.01,1000000.0);
1444 // gluPerspective(75.0,(GLfloat)Canvas_width/(GLfloat)Canvas_height,1.0,1000000.0);
1445 glMatrixMode(GL_MODELVIEW);
1446 glLoadIdentity();//clear matrix
1448 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1449 // glDisABLE(DITHER);
1450 // glScalef(1.0,1.0,-1.0);
1451 // glScalef(1.0,1.0,-1.0);
1454 // glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1455 // OGL_TEXENV(GL_TEXTURE_ENV_MODE,GL_MODULATE);
1456 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1457 // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1458 // OGL_TEXPARAM(GL_TEXTURE_MAG_FILTER,GL_texmagfilt);
1459 // OGL_TEXPARAM(GL_TEXTURE_MIN_FILTER,GL_texminfilt);
1460 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1461 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1464 void merge_textures_stats(void);
1466 void ogl_end_frame(void){
1467 // OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);
1468 OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1470 // merge_textures_stats();
1471 // ogl_texture_stats();
1473 // glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
1474 glMatrixMode(GL_PROJECTION);
1475 glLoadIdentity();//clear matrix
1476 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
1477 glMatrixMode(GL_MODELVIEW);
1478 glLoadIdentity();//clear matrix
1479 // glDisABLE(BLEND);
1480 //glDisABLE(ALPHA_TEST);
1481 //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
1482 // ogl_swap_buffers();//platform specific code
1483 // glClear(GL_COLOR_BUFFER_BIT);
1485 void ogl_swap_buffers(void){
1486 ogl_clean_texture_cache();
1487 if (gr_renderstats){
1488 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);
1489 // 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
1492 ogl_swap_buffers_internal();
1493 glClear(GL_COLOR_BUFFER_BIT);
1496 void ogl_init_shared_palette(void)
1498 #ifdef GL_EXT_paletted_texture
1499 if (ogl_shared_palette_ok)
1503 glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
1504 //glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGB, 256, GL_RGB, GL_UNSIGNED_BYTE, ogl_pal);
1506 for (i = 0; i < 256; i++)
1510 texbuf[i * 4] = 255;
1511 texbuf[i * 4 + 1] = 255;
1512 texbuf[i * 4 + 2] = 255;
1513 texbuf[i * 4 + 3] = 0;
1518 texbuf[i * 4 + 1] = 0;
1519 texbuf[i * 4 + 2] = 0;
1520 texbuf[i * 4 + 3] = 0;
1524 texbuf[i * 4] = gr_current_pal[i * 3] * 4;
1525 texbuf[i * 4 + 1] = gr_current_pal[i * 3 + 1] * 4;
1526 texbuf[i * 4 + 2] = gr_current_pal[i * 3 + 2] * 4;
1527 texbuf[i * 4 + 3] = 255;
1530 glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);
1535 int tex_format_supported(int iformat,int format){
1538 if (!ogl_intensity4_ok) return 0; break;
1539 case GL_LUMINANCE4_ALPHA4:
1540 if (!ogl_luminance4_alpha4_ok) return 0; break;
1542 if (!ogl_rgba2_ok) return 0; break;
1544 if (ogl_gettexlevelparam_ok){
1545 GLint internalFormat;
1546 glTexImage2D(GL_PROXY_TEXTURE_2D, 0, iformat, 64, 64, 0,
1547 format, GL_UNSIGNED_BYTE, texbuf);//NULL?
1548 glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0,
1549 GL_TEXTURE_INTERNAL_FORMAT,
1551 return (internalFormat==iformat);
1556 //little hack to find the largest or equal multiple of 2 for a given number
1560 for (i = 1; i <= 4096; i *= 2)
1565 //GLubyte texbuf[512*512*4];
1566 GLubyte texbuf[OGLTEXBUFSIZE];
1568 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)
1570 // GLushort *tex=(GLushort *)texp;
1572 if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
1573 Error("texture toobig %i %i",twidth,theight);
1576 for (y=0;y<theight;y++){
1577 i=dxo+truewidth*(y+dyo);
1578 for (x=0;x<twidth;x++){
1579 if (x<width && y<height)
1584 for (j = 0; j < data_format; ++j)
1585 (*(texp++)) = data[i * data_format + j];
1592 c = 256; // fill the pad space with transparency (or blackness)
1593 if (c == 254 && (bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1597 case GL_LUMINANCE_ALPHA:
1605 (*(texp++)) = 0; // transparent pixel
1607 case GL_COLOR_INDEX:
1611 Error("ogl_filltexbuf unhandled super-transparent texformat\n");
1615 else if ((c == 255 && (bm_flags & BM_FLAG_TRANSPARENT)) || c == 256)
1621 case GL_LUMINANCE_ALPHA:
1634 (*(texp++))=0;//transparent pixel
1636 case GL_COLOR_INDEX:
1640 Error("ogl_filltexbuf unknown texformat\n");
1645 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. :)
1648 case GL_LUMINANCE_ALPHA:
1653 (*(texp++)) = ogl_pal[c * 3] * 4;
1654 (*(texp++)) = ogl_pal[c * 3 + 1] * 4;
1655 (*(texp++)) = ogl_pal[c * 3 + 2] * 4;
1658 //(*(texp++))=gr_palette[c*3]*4;
1659 //(*(texp++))=gr_palette[c*3+1]*4;
1660 //(*(texp++))=gr_palette[c*3+2]*4;
1661 (*(texp++))=ogl_pal[c*3]*4;
1662 (*(texp++))=ogl_pal[c*3+1]*4;
1663 (*(texp++))=ogl_pal[c*3+2]*4;
1664 (*(texp++))=255;//not transparent
1665 // (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
1667 case GL_COLOR_INDEX:
1671 Error("ogl_filltexbuf unknown texformat\n");
1678 int tex_format_verify(ogl_texture *tex){
1679 while (!tex_format_supported(tex->internalformat,tex->format)){
1680 glmprintf((0,"tex format %x not supported",tex->internalformat));
1681 switch (tex->internalformat){
1683 if (ogl_luminance4_alpha4_ok){
1684 tex->internalformat=GL_LUMINANCE4_ALPHA4;
1685 tex->format=GL_LUMINANCE_ALPHA;
1687 }//note how it will fall through here if the statement is false
1688 case GL_LUMINANCE4_ALPHA4:
1690 tex->internalformat=GL_RGBA2;
1691 tex->format=GL_RGBA;
1693 }//note how it will fall through here if the statement is false
1695 tex->internalformat = ogl_rgba_internalformat;
1696 tex->format=GL_RGBA;
1699 mprintf((0,"...no tex format to fall back on\n"));
1702 glmprintf((0,"...falling back to %x\n",tex->internalformat));
1706 void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){
1708 if (tex->tw!=w || tex->th!=h){
1709 u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h);
1710 glmprintf((0,"shrunken texture?\n"));
1713 if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions.
1714 tex->bytes=((float)w*h*dbits)/8.0;
1715 tex->bytesu=((float)u*dbits)/8.0;
1717 tex->bytes=((float)w*h*bits)/8.0;
1718 tex->bytesu=((float)u*bits)/8.0;
1720 glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes));
1722 void tex_set_size(ogl_texture *tex){
1725 if (ogl_gettexlevelparam_ok){
1727 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w);
1728 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h);
1729 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t;
1730 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t;
1731 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t;
1732 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t;
1733 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t;
1734 glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t;
1735 #ifdef GL_EXT_paletted_texture
1736 if (ogl_paletted_texture_ok)
1738 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INDEX_SIZE_EXT, &t);
1746 switch (tex->format){
1750 case GL_LUMINANCE_ALPHA:
1757 case GL_COLOR_INDEX:
1761 Error("tex_set_size unknown texformat\n");
1764 tex_set_size1(tex,bi,a,w,h);
1766 //loads a palettized bitmap into a ogl RGBA texture.
1767 //Sizes and pads dimensions to multiples of 2 if necessary.
1768 //In theory this could be a problem for repeating textures, but all real
1769 //textures (not sprites, etc) in descent are 64x64, so we are ok.
1770 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
1771 void ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format)
1773 //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
1774 // int internalformat=GL_RGBA;
1775 // int format=GL_RGBA;
1777 tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
1778 // tex->tw=tex->w;tex->th=tex->h;//feeling lucky?
1780 if(gr_badtexture>0) return;
1782 #if !(defined(__APPLE__) && defined(__MACH__))
1783 // always fails on OS X, but textures work fine!
1784 if (tex_format_verify(tex))
1788 //calculate u/v values that would make the resulting texture correctly sized
1789 tex->u=(float)tex->w/(float)tex->tw;
1790 tex->v=(float)tex->h/(float)tex->th;
1792 #ifdef GL_EXT_paletted_texture
1793 if (ogl_shared_palette_ok && data_format == 0 && (tex->format == GL_RGBA || tex->format == GL_RGB) &&
1794 !(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.
1797 // descent makes palette entries 254 and 255 both do double duty, depending upon the setting of BM_FLAG_SUPER_TRANSPARENT and BM_FLAG_TRANSPARENT.
1798 // 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.)
1799 // We don't handle super transparent textures with ogl yet, so we don't bother checking that here.
1800 int usesthetransparentindexcolor = 0, usesthesupertransparentindexcolor = 0;
1802 if (!(bm_flags & BM_FLAG_SUPER_TRANSPARENT))
1806 for (i = 0; i < tex->w * tex->h; ++i)
1808 usesthesupertransparentindexcolor += 1;
1810 if (!(bm_flags & BM_FLAG_TRANSPARENT))
1814 for (i=0; i < tex->w * tex->h; ++i)
1816 usesthetransparentindexcolor += 1;
1818 if (!usesthetransparentindexcolor && !usesthesupertransparentindexcolor)
1820 tex->internalformat = GL_COLOR_INDEX8_EXT;
1821 tex->format = GL_COLOR_INDEX;
1824 // printf("bm data=%p w=%i h=%i transparent:%i supertrans:%i\n", data, tex->w, tex->h, usesthetransparentindexcolor, usesthesupertransparentindexcolor);
1828 // if (width!=twidth || height!=theight)
1829 // glmprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
1830 ogl_filltexbuf(data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags, data_format);
1832 // Generate OpenGL texture IDs.
1833 glGenTextures(1, &tex->handle);
1836 glPrioritizeTextures(1,&tex->handle,&tex->prio);
1838 // Give our data to OpenGL.
1840 OGL_BINDTEXTURE(tex->handle);
1842 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1844 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
1845 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_texminfilt);
1846 if (ogl_ext_texture_filter_anisotropic_ok && GL_texanisofilt)
1847 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_texanisofilt);
1851 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1852 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1854 // domipmap=0;//mipmaps aren't used in GL_NEAREST anyway, and making the mipmaps is pretty slow
1855 //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.
1857 if (tex->wantmip && GL_needmipmaps)
1858 gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
1859 tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
1861 glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
1862 tex->tw, tex->th, 0, tex->format, // RGBA textures.
1863 GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
1869 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));
1873 unsigned char decodebuf[512*512];
1875 void ogl_loadbmtexture_f(grs_bitmap *bm, int flags)
1882 while (bm->bm_parent)
1884 if (bm->gltexture && bm->gltexture->handle > 0)
1888 if ((bitmapname = piggy_game_bitmap_name(bm)))
1893 sprintf(filename, "textures/%s.png", bitmapname);
1894 if (read_png(filename, &pdata))
1896 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);
1897 if (pdata.depth == 8 && pdata.color)
1899 if (bm->gltexture == NULL)
1900 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));
1901 ogl_loadtexture(pdata.data, 0, 0, bm->gltexture, bm->bm_flags, pdata.paletted ? 0 : pdata.channels);
1904 free(pdata.palette);
1909 printf("%s: unsupported texture format: must be rgb, rgba, or paletted, and depth 8\n", filename);
1912 free(pdata.palette);
1917 if (bm->gltexture == NULL){
1918 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));
1921 if (bm->gltexture->handle>0)
1923 if (bm->gltexture->w==0){
1924 bm->gltexture->lw=bm->bm_w;
1925 bm->gltexture->w=bm->bm_w;
1926 bm->gltexture->h=bm->bm_h;
1929 if (bm->bm_flags & BM_FLAG_RLE){
1930 unsigned char * dbits;
1931 unsigned char * sbits;
1935 if (bm->bm_flags & BM_FLAG_RLE_BIG)
1938 sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)];
1941 for (i=0; i < bm->bm_h; i++ ) {
1942 gr_rle_decode(sbits,dbits);
1943 if ( bm->bm_flags & BM_FLAG_RLE_BIG )
1944 sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)])));
1946 sbits += (int)bm->bm_data[4+i];
1951 ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags, 0);
1954 void ogl_loadbmtexture(grs_bitmap *bm)
1956 ogl_loadbmtexture_f(bm, OGL_FLAG_MIPMAP);
1959 void ogl_freetexture(ogl_texture *gltexture)
1961 if (gltexture->handle>0) {
1963 glmprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
1964 glDeleteTextures( 1, &gltexture->handle );
1965 // gltexture->handle=0;
1966 ogl_reset_texture(gltexture);
1969 void ogl_freebmtexture(grs_bitmap *bm){
1971 ogl_freetexture(bm->gltexture);
1974 // glmprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
1975 // glDeleteTextures( 1, &bm->gltexture );
1976 // bm->gltexture=-1;