Difference for arch/ogl/ogl.c from version 1.12 to 1.13


version 1.12 version 1.13
Line 1
 
Line 1
 //#include <stdio.h>  //#include <stdio.h>
 #ifdef __WINDOWS__  #ifdef __WINDOWS__
 #include <windows.h>  #include <windows.h>
   #include <stddef.h>
 #endif  #endif
 #include <GL/gl.h>  #include <GL/gl.h>
 #include <GL/glu.h>  #include <GL/glu.h>
   #include "ogl_init.h"
 #include "3d.h"  #include "3d.h"
 #include "piggy.h"  #include "piggy.h"
 #include "../../3d/globvars.h"  #include "../../3d/globvars.h"
Line 11
 
Line 13
 #include "texmap.h"  #include "texmap.h"
 #include "palette.h"  #include "palette.h"
 #include "rle.h"  #include "rle.h"
 #include "ogl_init.h"  
 #include "mono.h"  #include "mono.h"
   
 #include "segment.h"  #include "segment.h"
Line 21
 
Line 22
 #include "weapon.h"  #include "weapon.h"
 #include "powerup.h"  #include "powerup.h"
 #include "polyobj.h"  #include "polyobj.h"
   #include "gamefont.h"
   
 unsigned char *ogl_pal=gr_palette;  unsigned char *ogl_pal=gr_palette;
   
Line 32
 
Line 34
 int GL_TEXTURE_2D_enabled=-1;  int GL_TEXTURE_2D_enabled=-1;
 int GL_texclamp_enabled=-1;  int GL_texclamp_enabled=-1;
   
   extern int gr_renderstats;
   extern int gr_badtexture;
   int ogl_alttexmerge=0;//merge textures by just printing the seperate textures?
   int ogl_16bittextures=0;
   
   //int lastbound=-1;
   
   //#define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
   // else if(a!=lastbound) {glBindTexture(GL_TEXTURE_2D, a);lastbound=a;}
   #define OGL_BINDTEXTURE(a) if(gr_badtexture>0) glBindTexture(GL_TEXTURE_2D, 0);\
    else glBindTexture(GL_TEXTURE_2D, a);
   
   
   ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE];
   int ogl_texture_list_cur;
   
   void ogl_init_texture_stats(ogl_texture* t){
    t->prio=0.3;//default prio
    t->lastrend=0;
    t->numrend=0;
   }
   void ogl_init_texture(ogl_texture* t){
    t->handle=0;
    if (ogl_16bittextures)
    t->internalformat=GL_RGB5_A1;
    else
    t->internalformat=4;
    t->format=GL_RGBA;
    t->wrapstate=-1;
    t->w=t->h=0;
    ogl_init_texture_stats(t);
   }
   void ogl_reset_texture_stats_internal(void){
    int i;
    for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
    if (ogl_texture_list[i].handle>0){
    ogl_init_texture_stats(&ogl_texture_list[i]);
    }
   }
   void ogl_init_texture_list_internal(void){
    int i;
    ogl_texture_list_cur=0;
    for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++)
    ogl_init_texture(&ogl_texture_list[i]);
   }
   void ogl_smash_texture_list_internal(void){
    int i;
    for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
    ogl_texture_list[i].handle=0;
    ogl_texture_list[i].wrapstate=-1;
    }
   }
   
   ogl_texture* ogl_get_free_texture(void){
    int i;
    for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
    if (ogl_texture_list[ogl_texture_list_cur].handle<=0 && ogl_texture_list[ogl_texture_list_cur].w==0)
    return &ogl_texture_list[ogl_texture_list_cur];
    if (++ogl_texture_list_cur>=OGL_TEXTURE_LIST_SIZE)
    ogl_texture_list_cur=0;
    }
    Error("OGL: texture list full!\n");
   // return NULL;
   }
   int ogl_texture_bytes_used(ogl_texture* t){
    switch (t->internalformat){
    case GL_LUMINANCE4_ALPHA4:
    return t->tw*t->th;
    case GL_RGB5_A1:
    return t->tw*t->th*2;
    default:
    return t->tw*t->th*4;
    }
   }
   int ogl_texture_stats(void){
    int used=0,usedl4a4=0,usedrgba=0,databytes=0,truebytes=0,datatexel=0,truetexel=0,i;
    int prio0=0,prio1=0,prio2=0,prio3=0,prioh=0;
   // int grabbed=0;
    ogl_texture* t;
    for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
    t=&ogl_texture_list[i];
    if (t->handle>0){
    used++;
    datatexel+=t->w*t->h;
    truetexel+=t->tw*t->th;
    switch (t->internalformat){
    case GL_LUMINANCE4_ALPHA4:
    databytes+=t->w*t->h;
    truebytes+=t->tw*t->th;
    usedl4a4++;
    break;
    case GL_RGB5_A1:
    databytes+=t->w*t->h*2;
    truebytes+=t->tw*t->th*2;
    usedrgba++;
    break;
    default:
    databytes+=t->w*t->h*4;
    truebytes+=t->tw*t->th*4;
    usedrgba++;
    }
    if (t->prio<0.299)prio0++;
    else if (t->prio<0.399)prio1++;
    else if (t->prio<0.499)prio2++;
    else if (t->prio<0.599)prio3++;
    else prioh++;
    }
   // else if(t->w!=0)
   // grabbed++;
    }
    if (gr_renderstats){
    gr_printf(5,GAME_FONT->ft_h*14+3*14,"%i(%i,%i) %iK(%iK wasted)",used,usedrgba,usedl4a4,truebytes/1024,(truebytes-databytes)/1024);
    }
   // mprintf((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));
    return truebytes;
   }
   int ogl_mem_target=-1;
   void ogl_clean_texture_cache(void){
    ogl_texture* t;
    int i,bytes;
    int time=120;
   
    if (ogl_mem_target<0){
    if (gr_renderstats)
    ogl_texture_stats();
    return;
    }
   
    bytes=ogl_texture_stats();
    while (bytes>ogl_mem_target){
    for (i=0;i<OGL_TEXTURE_LIST_SIZE;i++){
    t=&ogl_texture_list[i];
    if (t->handle>0){
    if (t->lastrend+f1_0*time<GameTime){
    ogl_freetexture(t);
    bytes-=ogl_texture_bytes_used(t);
    if (bytes<ogl_mem_target)
    return;
    }
    }
    }
    if (time==0)
    Error("not enough mem?");
    time=time/2;
    }
   
   }
   void ogl_bindbmtex(grs_bitmap *bm){
    if (bm->gltexture==NULL || bm->gltexture->handle<=0)
    ogl_loadbmtexture(bm);
    OGL_BINDTEXTURE(bm->gltexture->handle);
    bm->gltexture->lastrend=GameTime;
    bm->gltexture->numrend++;
    if (bm->gltexture->numrend==80 || bm->gltexture->numrend==4000 || bm->gltexture->numrend==80000){
    bm->gltexture->prio+=0.1;
   // glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_PRIORITY,bm->gltexture->prio);
    glPrioritizeTextures(1,&bm->gltexture->handle,&bm->gltexture->prio);
    }
   }
   //gltexture MUST be bound first
   void ogl_texwrap(ogl_texture *gltexture,int state){
    if (gltexture->wrapstate!=state || gltexture->numrend<1){
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state);
    gltexture->wrapstate=state;
    }
   }
   
 //crude texture precaching  //crude texture precaching
 //handles: powerups, walls, weapons, polymodels, etc.  //handles: powerups, walls, weapons, polymodels, etc.
 //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.  //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.
Line 67
 
Line 237
  int seg,side,i;   int seg,side,i;
  eclip *ec;   eclip *ec;
  short tmap1,tmap2;   short tmap1,tmap2;
  grs_bitmap *bm;   grs_bitmap *bm,*bm2;
  struct side *sidep;   struct side *sidep;
  int max_efx=0,ef;   int max_efx=0,ef;
   
    ogl_reset_texture_stats_internal();//loading a new lev should reset textures
   
  for (i=0,ec=Effects;i<Num_effects;i++,ec++) {   for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
  if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )   if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
  continue;   continue;
Line 97
 
Line 270
  // tmap1=0;   // tmap1=0;
  continue;   continue;
  }   }
    PIGGY_PAGE_IN(Textures[tmap1]);
    bm = &GameBitmaps[Textures[tmap1].index];
  if (tmap2 != 0){   if (tmap2 != 0){
    PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]);
    bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index];
    if (ogl_alttexmerge==0 || (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT))
  bm = texmerge_get_cached_bitmap( tmap1, tmap2 );   bm = texmerge_get_cached_bitmap( tmap1, tmap2 );
  // mprintf((0,"ogl_cache_level_textures seg %i side %i t1 %i t2 %x bm %p NT %i\n",seg,side,tmap1,tmap2,bm,NumTextures));  
  }  
  else    {   else    {
  PIGGY_PAGE_IN(Textures[tmap1]);   ogl_loadbmtexture(bm2);
  bm = &GameBitmaps[Textures[tmap1].index];   }
  // mprintf((0,"ogl_cache_level_textures seg %i side %i t1 %i t2 %x idx %i bm %p NT %i\n",seg,side,tmap1,tmap2,Textures[tmap1].index,bm,NumTextures));   // mprintf((0,"ogl_cache_level_textures seg %i side %i t1 %i t2 %x bm %p NT %i\n",seg,side,tmap1,tmap2,bm,NumTextures));
  }   }
  ogl_loadbmtexture(bm);   ogl_loadbmtexture(bm);
  }   }
Line 174
 
Line 350
 {  {
  int c;   int c;
  c=grd_curcanv->cv_color;   c=grd_curcanv->cv_color;
  OGL_DISABLE(GL_TEXTURE_2D);   OGL_DISABLE(TEXTURE_2D);
  glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));   glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
  glBegin(GL_LINES);   glBegin(GL_LINES);
  glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));   glVertex3f(f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z));
Line 186
 
Line 362
 int g3_draw_sphere(g3s_point *pnt,fix rad){  int g3_draw_sphere(g3s_point *pnt,fix rad){
  int c;   int c;
  c=grd_curcanv->cv_color;   c=grd_curcanv->cv_color;
  OGL_DISABLE(GL_TEXTURE_2D);   OGL_DISABLE(TEXTURE_2D);
  glPointSize(f2glf(rad));   glPointSize(f2glf(rad));
  glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));   glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
  glBegin(GL_POINTS);   glBegin(GL_POINTS);
Line 202
 
Line 378
  r_polyc++;   r_polyc++;
  c=grd_curcanv->cv_color;   c=grd_curcanv->cv_color;
 // 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);  // 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);
  OGL_DISABLE(GL_TEXTURE_2D);   OGL_DISABLE(TEXTURE_2D);
  glBegin(GL_TRIANGLE_FAN);   glBegin(GL_TRIANGLE_FAN);
  glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));   glColor3f(PAL2Tr(c),PAL2Tg(c),PAL2Tb(c));
  for (c=0;c<nv;c++){   for (c=0;c<nv;c++){
Line 212
 
Line 388
  glEnd();   glEnd();
  return 0;   return 0;
 }  }
   
   void gr_upoly_tmap(int nverts, int *vert ){
    mprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called
   }
   void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){
    mprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called
   }
   extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist);
 bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)  bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bm)
 {  {
  int c;   int c;
  float l;   float l;
    if (tmap_drawer_ptr==draw_tmap_flat){
   /* fix average_light=0;
    int i;
    for (i=0; i<nv; i++)
    average_light += uvl_list[i].l;*/
    OGL_DISABLE(TEXTURE_2D);
   // mprintf((0,"Gr_scanline_darkening_level=%i %f\n",Gr_scanline_darkening_level,Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
    glColor4f(0,0,0,1.0-(Gr_scanline_darkening_level/(float)NUM_LIGHTING_LEVELS));
    //glColor4f(0,0,0,f2fl(average_light/nv));
    glBegin(GL_TRIANGLE_FAN);
    for (c=0;c<nv;c++){
   // glColor4f(0,0,0,f2fl(uvl_list[c].l));
   // glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
    glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
    }
    glEnd();
    }else if (tmap_drawer_ptr==draw_tmap){
  r_tpolyc++;   r_tpolyc++;
 /* if (bm->bm_w !=64||bm->bm_h!=64)  /* if (bm->bm_w !=64||bm->bm_h!=64)
  printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/   printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
  OGL_ENABLE(GL_TEXTURE_2D);   OGL_ENABLE(TEXTURE_2D);
  if (bm->gltexture<0)   ogl_bindbmtex(bm);
  ogl_loadbmtexture(bm);   ogl_texwrap(bm->gltexture,GL_REPEAT);
  glBindTexture(GL_TEXTURE_2D, bm->gltexture);  
  OGL_TEXREPEAT();  
  glBegin(GL_TRIANGLE_FAN);   glBegin(GL_TRIANGLE_FAN);
  for (c=0;c<nv;c++){   for (c=0;c<nv;c++){
  if (bm->bm_flags&BM_FLAG_NO_LIGHTING){   if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
Line 235
 
Line 434
  glColor3f(l,l,l);   glColor3f(l,l,l);
  glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));   glTexCoord2f(f2glf(uvl_list[c].u),f2glf(uvl_list[c].v));
  //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));   //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
    glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
    }
    glEnd();
    }else{
    mprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr));
    }
    return 0;
   }
   //int orient2uv[4][4]={{0,1,2,3},{;
   bool g3_draw_tmap_2(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,grs_bitmap *bmbot,grs_bitmap *bm,int orient)
   {
    int c;
    float l,u1,v1;
   
    g3_draw_tmap(nv,pointlist,uvl_list,bmbot);//draw the bottom texture first.. could be optimized with multitexturing..
   
    r_tpolyc++;
   /* if (bm->bm_w !=64||bm->bm_h!=64)
    printf("g3_draw_tmap w %i h %i\n",bm->bm_w,bm->bm_h);*/
    OGL_ENABLE(TEXTURE_2D);
    ogl_bindbmtex(bm);
    ogl_texwrap(bm->gltexture,GL_REPEAT);
    glBegin(GL_TRIANGLE_FAN);
    for (c=0;c<nv;c++){
   // oc=(c-orient);
   // if (oc<0)oc+=4;
   // else if (oc>4)oc-=4;
    switch(orient){
    case 1:
    u1=1.0-f2glf(uvl_list[c].v);
    v1=f2glf(uvl_list[c].u);
    break;
    case 2:
    u1=1.0-f2glf(uvl_list[c].u);
    v1=1.0-f2glf(uvl_list[c].v);
    break;
    case 3:
    u1=f2glf(uvl_list[c].v);
    v1=1.0-f2glf(uvl_list[c].u);
    break;
    default:
    u1=f2glf(uvl_list[c].u);
    v1=f2glf(uvl_list[c].v);
    break;
    }
    if (bm->bm_flags&BM_FLAG_NO_LIGHTING){
    l=1.0;
    }else{
    //l=f2fl(uvl_list[c].l)+gr_palette_gamma/63.0;
    l=f2fl(uvl_list[c].l);
    }
    glColor3f(l,l,l);
    glTexCoord2f(u1,v1);
    //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
  //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));   //glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),f2glf(pointlist[c]->p3_vec.z));
  glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));   glVertex3f(f2glf(pointlist[c]->p3_vec.x),f2glf(pointlist[c]->p3_vec.y),-f2glf(pointlist[c]->p3_vec.z));
  }   }
Line 252
 
Line 505
 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));  // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));  // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
   
  OGL_ENABLE(GL_TEXTURE_2D);   OGL_ENABLE(TEXTURE_2D);
  if (bm->gltexture<0)   ogl_bindbmtex(bm);
  ogl_loadbmtexture(bm);   ogl_texwrap(bm->gltexture,GL_CLAMP);
  glBindTexture(GL_TEXTURE_2D, bm->gltexture);  
    
  OGL_TEXCLAMP();  
   
  glBegin(GL_QUADS);   glBegin(GL_QUADS);
  glColor3f(1.0,1.0,1.0);   glColor3f(1.0,1.0,1.0);
Line 275
 
Line 525
  pv.y+=height;   pv.y+=height;
  break;   break;
  case 1:   case 1:
  glTexCoord2f(bm->glu, 0.0);   glTexCoord2f(bm->gltexture->u, 0.0);
  pv.x+=width;   pv.x+=width;
  pv.y+=height;   pv.y+=height;
  break;   break;
  case 2:   case 2:
  glTexCoord2f(bm->glu, bm->glv);   glTexCoord2f(bm->gltexture->u, bm->gltexture->v);
  pv.x+=width;   pv.x+=width;
  pv.y+=-height;   pv.y+=-height;
  break;   break;
  case 3:   case 3:
  glTexCoord2f(0.0, bm->glv);   glTexCoord2f(0.0, bm->gltexture->v);
  pv.x+=-width;   pv.x+=-width;
  pv.y+=-height;   pv.y+=-height;
  break;   break;
Line 305
 
Line 555
 bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)  bool ogl_ubitmapm_c(int x, int y,grs_bitmap *bm,int c)
 {  {
  GLfloat xo,yo,xf,yf;   GLfloat xo,yo,xf,yf;
    GLfloat u1,u2,v1,v2;
  r_ubitmapc++;   r_ubitmapc++;
  x+=grd_curcanv->cv_bitmap.bm_x;   x+=grd_curcanv->cv_bitmap.bm_x;
  y+=grd_curcanv->cv_bitmap.bm_y;   y+=grd_curcanv->cv_bitmap.bm_y;
Line 312
 
Line 563
  xf=(bm->bm_w+x)/(float)last_width;   xf=(bm->bm_w+x)/(float)last_width;
  yo=1.0-y/(float)last_height;   yo=1.0-y/(float)last_height;
  yf=1.0-(bm->bm_h+y)/(float)last_height;   yf=1.0-(bm->bm_h+y)/(float)last_height;
   
 // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));  // printf("g3_draw_bitmap: %f,%f,%f - ",f2glf(pos->x),f2glf(pos->y),-f2glf(pos->z));
 // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));  // printf("(%f,%f,%f) ",f2glf(View_position.x),f2glf(View_position.y),-f2glf(View_position.z));
   
 /* glEnable(GL_ALPHA_TEST);  /* glEnABLE(ALPHA_TEST);
  glAlphaFunc(GL_GREATER,0.0);*/   glAlphaFunc(GL_GREATER,0.0);*/
   
  OGL_ENABLE(GL_TEXTURE_2D);   OGL_ENABLE(TEXTURE_2D);
  if (bm->gltexture<0)   ogl_bindbmtex(bm);
  ogl_loadbmtexture(bm);   ogl_texwrap(bm->gltexture,GL_CLAMP);
  glBindTexture(GL_TEXTURE_2D, bm->gltexture);  
    if (bm->bm_x==0){
    u1=0;
    if (bm->bm_w==bm->gltexture->w)
    u2=bm->gltexture->u;
    else
    u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
    }else {
    u1=bm->bm_x/(float)bm->gltexture->tw;
    u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
    }
    if (bm->bm_y==0){
    v1=0;
    if (bm->bm_h==bm->gltexture->h)
    v2=bm->gltexture->v;
    else
    v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
    }else{
    v1=bm->bm_y/(float)bm->gltexture->th;
    v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
    }
   
   // u1=bm->bm_x/(float)bm->gltexture->tw;
   // u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw;
   // v1=bm->bm_y/(float)bm->gltexture->th;
   // v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th;
    
  OGL_TEXCLAMP();  
   
  glBegin(GL_QUADS);   glBegin(GL_QUADS);
  if (c<0)   if (c<0)
  glColor3f(1.0,1.0,1.0);   glColor3f(1.0,1.0,1.0);
  else   else
  glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));   glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
  glTexCoord2f(0.0, 0.0); glVertex2f(xo, yo);   glTexCoord2f(u1, v1); glVertex2f(xo, yo);
  glTexCoord2f(bm->glu, 0.0); glVertex2f(xf, yo);   glTexCoord2f(u2, v1); glVertex2f(xf, yo);
  glTexCoord2f(bm->glu, bm->glv); glVertex2f(xf, yf);   glTexCoord2f(u2, v2); glVertex2f(xf, yf);
  glTexCoord2f(0.0, bm->glv); glVertex2f(xo, yf);   glTexCoord2f(u1, v2); glVertex2f(xo, yf);
  glEnd();   glEnd();
 // glDisable(GL_ALPHA_TEST);  // glDisABLE(ALPHA_TEST);
    
  return 0;   return 0;
 }  }
 bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){  bool ogl_ubitmapm(int x, int y,grs_bitmap *bm){
  return ogl_ubitmapm_c(x,y,bm,-1);   return ogl_ubitmapm_c(x,y,bm,-1);
   // return ogl_ubitblt(bm->bm_w,bm->bm_h,x,y,0,0,bm,NULL);
 }  }
 #if 0  #if 0
 //also upsidedown, currently.  //also upsidedown, currently.
 bool ogl_ubitblt_notrans(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)  bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
 {  {
  GLfloat xo,yo,xs,ys;   GLfloat xo,yo;//,xs,ys;
    mprintf((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));
   
    dx+=grd_curcanv->cv_bitmap.bm_x;
    dy+=grd_curcanv->cv_bitmap.bm_y;
    
  xo=dx/(float)last_width;   xo=dx/(float)last_width;
  xs=w/(float)last_width;  // xo=dx/(float)grd_curscreen->sc_w;
   // xs=w/(float)last_width;
  //yo=1.0-dy/(float)last_height;   //yo=1.0-dy/(float)last_height;
  yo=dy/(float)last_height;   yo=1.0-(dy+h)/(float)last_height;
  ys=h/(float)last_height;  // ys=h/(float)last_height;
    
 // OGL_ENABLE(GL_TEXTURE_2D);  // OGL_ENABLE(TEXTURE_2D);
    
  OGL_DISABLE(GL_TEXTURE_2D);   OGL_DISABLE(TEXTURE_2D);
  glRasterPos2f(xo,yo);   glRasterPos2f(xo,yo);
  ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h);   ogl_filltexbuf(src->bm_data,texbuf,src->bm_w,w,h,sx,sy,w,h);
  glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);   glDrawPixels(w,h,GL_RGBA,GL_UNSIGNED_BYTE,texbuf);
Line 364
 
Line 646
    
  return 0;   return 0;
 }  }
 #endif  #else
 bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)  bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
 {  {
 // r_ubitbltc++;  // r_ubitbltc++;
 // return 0;  // return 0;
 //#if 0  //#if 0
  GLfloat xo,yo,xs,ys;   GLfloat xo,yo,xs,ys;
  GLfloat u1,v1,u2,v2;   GLfloat u1,v1;//,u2,v2;
  int gltexture=0;   ogl_texture tex;
   // int gltexture=0;
 // unsigned char *oldpal;  // unsigned char *oldpal;
  r_ubitbltc++;   r_ubitbltc++;
   
    ogl_init_texture(&tex);
    tex.w=w;tex.h=h;
    tex.prio=0.0;
   
 /* if (w==src->bm_w && sx==0){  /* if (w==src->bm_w && sx==0){
  u1=0;u2=src->glu;   u1=0;u2=src->glu;
  }else{   }else{
Line 397
 
Line 684
  yo=1.0-dy/(float)last_height;   yo=1.0-dy/(float)last_height;
  ys=h/(float)last_height;   ys=h/(float)last_height;
    
  OGL_ENABLE(GL_TEXTURE_2D);   OGL_ENABLE(TEXTURE_2D);
    
 // if (src->gltexture<0)  // if (src->gltexture<0)
 // oldpal=ogl_pal;  // oldpal=ogl_pal;
  ogl_pal=gr_current_pal;   ogl_pal=gr_current_pal;
  ogl_loadtexture(src->bm_data,w,h,sx,sy,&gltexture,&u2,&v2,0);   ogl_loadtexture(src->bm_data,0,0,&tex,0);
 // ogl_pal=oldpal;  // ogl_pal=oldpal;
  ogl_pal=gr_palette;   ogl_pal=gr_palette;
 // ogl_loadbmtexture(src);  // ogl_loadbmtexture(src);
 // else  // else
 // alreadygl=1;  // alreadygl=1;
  glBindTexture(GL_TEXTURE_2D, gltexture);   OGL_BINDTEXTURE(tex.handle);
    
  OGL_TEXCLAMP();   ogl_texwrap(&tex,GL_CLAMP);
   
  glBegin(GL_QUADS);   glBegin(GL_QUADS);
  glColor3f(1.0,1.0,1.0);   glColor3f(1.0,1.0,1.0);
  glTexCoord2f(u1, v1); glVertex2f(xo, yo);   glTexCoord2f(u1, v1); glVertex2f(xo, yo);
  glTexCoord2f(u2, v1); glVertex2f(xo+xs, yo);   glTexCoord2f(tex.u, v1); glVertex2f(xo+xs, yo);
  glTexCoord2f(u2, v2); glVertex2f(xo+xs, yo-ys);   glTexCoord2f(tex.u, tex.v); glVertex2f(xo+xs, yo-ys);
  glTexCoord2f(u1, v2); glVertex2f(xo, yo-ys);   glTexCoord2f(u1, tex.v); glVertex2f(xo, yo-ys);
  glEnd();   glEnd();
 // if(!alreadygl)   // if(!alreadygl)
 // ogl_freebmtexture(src);  // ogl_freebmtexture(src);
  ogl_freetexture(&gltexture);   ogl_freetexture(&tex);
  return 0;   return 0;
 //#endif  //#endif
 }  }
   #endif
   
 void ogl_start_frame(void){  void ogl_start_frame(void){
  r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;   r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitmapc=0;r_ubitbltc=0;r_upixelc=0;
   // gl_badtexture=500;
   
  OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);   OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height);
  glClearColor(0.0, 0.0, 0.0, 0.0);   glClearColor(0.0, 0.0, 0.0, 0.0);
 // glEnable(GL_ALPHA_TEST);  // glEnable(GL_ALPHA_TEST);
 // glAlphaFunc(GL_GREATER,0.0);  // glAlphaFunc(GL_GREATER,0.01);
  glShadeModel(GL_SMOOTH);   glShadeModel(GL_SMOOTH);
  glMatrixMode(GL_PROJECTION);   glMatrixMode(GL_PROJECTION);
  glLoadIdentity();//clear matrix   glLoadIdentity();//clear matrix
Line 445
 
Line 734
  glLoadIdentity();//clear matrix   glLoadIdentity();//clear matrix
  glEnable(GL_BLEND);   glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 // glDisable(GL_DITHER);  // glDisABLE(DITHER);
 // glScalef(1.0,1.0,-1.0);  // glScalef(1.0,1.0,-1.0);
 // glScalef(1.0,1.0,-1.0);  // glScalef(1.0,1.0,-1.0);
 // glPushMatrix();  // glPushMatrix();
Line 459
 
Line 748
 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  // glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 }  }
   #ifndef NMONO
   void merge_textures_stats(void);
   #endif
 void ogl_end_frame(void){  void ogl_end_frame(void){
 // OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);  // OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,);
  OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);   OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
  mprintf((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));  #ifndef NMONO
   // merge_textures_stats();
   // ogl_texture_stats();
   #endif
 // glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);  // glViewport(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
  glMatrixMode(GL_PROJECTION);   glMatrixMode(GL_PROJECTION);
  glLoadIdentity();//clear matrix   glLoadIdentity();//clear matrix
  glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);   glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
  glMatrixMode(GL_MODELVIEW);   glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();//clear matrix   glLoadIdentity();//clear matrix
 // glDisable(GL_BLEND);  // glDisABLE(BLEND);
  //glDisable(GL_ALPHA_TEST);   //glDisABLE(ALPHA_TEST);
  //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);   //gluPerspective(90.0,(GLfloat)(grd_curscreen->sc_w*3)/(GLfloat)(grd_curscreen->sc_h*4),1.0,1000000.0);
 // ogl_swap_buffers();//platform specific code  // ogl_swap_buffers();//platform specific code
 // glClear(GL_COLOR_BUFFER_BIT);  // glClear(GL_COLOR_BUFFER_BIT);
   
   }
   void ogl_swap_buffers(void){
    ogl_clean_texture_cache();
    if (gr_renderstats){
    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);
   // mprintf((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
    }
    ogl_do_palfx();
    ogl_swap_buffers_internal();
    glClear(GL_COLOR_BUFFER_BIT);
 }  }
   
 //little hack to find the largest or equal multiple of 2 for a given number  //little hack to find the largest or equal multiple of 2 for a given number
Line 486
 
Line 792
   
 //GLubyte texbuf[512*512*4];  //GLubyte texbuf[512*512*4];
 GLubyte texbuf[OGLTEXBUFSIZE];  GLubyte texbuf[OGLTEXBUFSIZE];
 void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int truewidth,int width,int height,int dxo,int dyo,int twidth,int theight)  void ogl_filltexbuf(unsigned char *data,GLubyte *texp,int truewidth,int width,int height,int dxo,int dyo,int twidth,int theight,int type)
 {  {
   // GLushort *tex=(GLushort *)texp;
  int x,y,c,i;   int x,y,c,i;
  if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.   if (twidth*theight*4>sizeof(texbuf))//shouldn't happen, descent never uses textures that big.
  Error("texture toobig %i %i",twidth,theight);   Error("texture toobig %i %i",twidth,theight);
Line 501
 
Line 808
  else   else
  c=255;//fill the pad space with transparancy   c=255;//fill the pad space with transparancy
  if (c==255){   if (c==255){
    if (type==-2){
    (*(texp++))=0;
    (*(texp++))=0;
    }else{
  (*(texp++))=0;   (*(texp++))=0;
  (*(texp++))=0;   (*(texp++))=0;
  (*(texp++))=0;   (*(texp++))=0;
  (*(texp++))=0;//transparent pixel   (*(texp++))=0;//transparent pixel
    }
   // (*(tex++))=0;
    }else{
    if (type==-2){
    (*(texp++))=255;
    (*(texp++))=255;
  }else{   }else{
  //(*(texp++))=gr_palette[c*3]*4;   //(*(texp++))=gr_palette[c*3]*4;
  //(*(texp++))=gr_palette[c*3+1]*4;   //(*(texp++))=gr_palette[c*3+1]*4;
Line 513
 
Line 830
  (*(texp++))=ogl_pal[c*3+1]*4;   (*(texp++))=ogl_pal[c*3+1]*4;
  (*(texp++))=ogl_pal[c*3+2]*4;   (*(texp++))=ogl_pal[c*3+2]*4;
  (*(texp++))=255;//not transparent   (*(texp++))=255;//not transparent
    // (*(tex++))=(ogl_pal[c*3]>>1) + ((ogl_pal[c*3+1]>>1)<<5) + ((ogl_pal[c*3+2]>>1)<<10) + (1<<15);
    }
  }   }
  }   }
  }   }
Line 522
 
Line 841
 //In theory this could be a problem for repeating textures, but all real  //In theory this could be a problem for repeating textures, but all real
 //textures (not sprites, etc) in descent are 64x64, so we are ok.  //textures (not sprites, etc) in descent are 64x64, so we are ok.
 //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v  //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v
 void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,int domipmap){  void ogl_loadtexture(unsigned char * data, int dxo,int dyo, ogl_texture *tex,char domipmap){
  int twidth=pow2ize(width),theight=pow2ize(height);//calculate smallest texture size that can accomodate us (must be multiples of 2)  //void ogl_loadtexture(unsigned char * data, int width, int height,int dxo,int dyo, int *texid,float *u,float *v,char domipmap,float prio){
   // int internalformat=GL_RGBA;
   // int format=GL_RGBA;
    int filltype=0;
    tex->tw=pow2ize(tex->w);tex->th=pow2ize(tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2)
   
    if(gr_badtexture>0) return;
   
    if (tex->handle==-2){
   // internalformat=GL_INTENSITY4;
   // format=GL_LUMINANCE;
    tex->internalformat=GL_LUMINANCE4_ALPHA4;
    tex->format=GL_LUMINANCE_ALPHA;
    }
    if (tex->format==GL_LUMINANCE_ALPHA)
    filltype=-2;
   
  //calculate u/v values that would make the resulting texture correctly sized   //calculate u/v values that would make the resulting texture correctly sized
  *u=(float)width/(float)twidth;   tex->u=(float)tex->w/(float)tex->tw;
  *v=(float)height/(float)theight;   tex->v=(float)tex->h/(float)tex->th;
   
  // if (width!=twidth || height!=theight)   // if (width!=twidth || height!=theight)
  // mprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));   // mprintf((0,"sizing %ix%i texture up to %ix%i\n",width,height,twidth,theight));
  ogl_filltexbuf(data,texbuf,width,width,height,dxo,dyo,twidth,theight);   ogl_filltexbuf(data,texbuf,tex->w,tex->w,tex->h,dxo,dyo,tex->tw,tex->th,filltype);
   
  // Generate OpenGL texture IDs.   // Generate OpenGL texture IDs.
  glGenTextures(1, texid);   glGenTextures(1, &tex->handle);
   
    //set priority
    glPrioritizeTextures(1,&tex->handle,&tex->prio);
   
  // Give our data to OpenGL.   // Give our data to OpenGL.
   
  glBindTexture(GL_TEXTURE_2D, *texid);   OGL_BINDTEXTURE(tex->handle);
   
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_texmagfilt);
Line 547
 
Line 884
  //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.   //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.
   
  if (domipmap && GL_needmipmaps)   if (domipmap && GL_needmipmaps)
  gluBuild2DMipmaps( GL_TEXTURE_2D, 4, twidth,   gluBuild2DMipmaps( GL_TEXTURE_2D, tex->internalformat, tex->tw,
  theight, GL_RGBA, GL_UNSIGNED_BYTE, texbuf);   tex->th, tex->format, GL_UNSIGNED_BYTE, texbuf);
  else   else
  glTexImage2D(GL_TEXTURE_2D, 0, 4,   glTexImage2D(GL_TEXTURE_2D, 0, tex->internalformat,
  twidth, theight, 0, GL_RGBA, // RGBA textures.   tex->tw, tex->th, 0, tex->format, // RGBA textures.
  GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.   GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer.
  texbuf);   texbuf);
  r_texcount++;   r_texcount++;
  mprintf((0,"ogl_loadtexture(%p,%i,%i,%ix%i,%p):%i u=%f v=%f (%i)\n",data,twidth,theight,dxo,dyo,texid,*texid,*u,*v,r_texcount));   mprintf((0,"ogl_loadtexture(%p,%i,%i,%ix%i,%p):%i u=%f v=%f (%i)\n",data,tex->tw,tex->th,dxo,dyo,tex,tex->handle,tex->u,tex->v,r_texcount));
   
 }  }
 unsigned char decodebuf[512*512];  unsigned char decodebuf[512*512];
 void ogl_loadbmtexture_m(grs_bitmap *bm,int domipmap){  void ogl_loadbmtexture_m(grs_bitmap *bm,int domipmap){
  unsigned char *buf=bm->bm_data;   unsigned char *buf=bm->bm_data;
  if (bm->gltexture>=0)   if (bm->gltexture==NULL){
    ogl_init_texture(bm->gltexture=ogl_get_free_texture());
    }
    else if (bm->gltexture->handle>0)
  return;   return;
    bm->gltexture->w=bm->bm_w;
    bm->gltexture->h=bm->bm_h;
  if (bm->bm_flags & BM_FLAG_RLE){   if (bm->bm_flags & BM_FLAG_RLE){
  unsigned char * dbits;   unsigned char * dbits;
  unsigned char * sbits;   unsigned char * sbits;
Line 577
 
Line 919
  }   }
  buf=decodebuf;   buf=decodebuf;
  }   }
  ogl_loadtexture(buf,bm->bm_w,bm->bm_h,0,0,&bm->gltexture,&bm->glu,&bm->glv,domipmap);   ogl_loadtexture(buf,0,0,bm->gltexture,domipmap);
 }  }
 void ogl_loadbmtexture(grs_bitmap *bm){  void ogl_loadbmtexture(grs_bitmap *bm){
  ogl_loadbmtexture_m(bm,1);   ogl_loadbmtexture_m(bm,1);
 }  }
 void ogl_freetexture(int *gltexture){  void ogl_freetexture(ogl_texture *gltexture){
  if (*gltexture>=0){   if (gltexture->handle>=0){
  r_texcount--;   r_texcount--;
  mprintf((0,"ogl_freetexture(%p):%i (%i left)\n",gltexture,*gltexture,r_texcount));   mprintf((0,"ogl_freetexture(%p):%i (last rend %is) (%i left)\n",gltexture,gltexture->handle,(GameTime-gltexture->lastrend)/f1_0,r_texcount));
  glDeleteTextures( 1, gltexture );   glDeleteTextures( 1, &gltexture->handle );
  *gltexture=-1;  // gltexture->handle=0;
    ogl_init_texture(gltexture);
  }   }
 }  }
 void ogl_freebmtexture(grs_bitmap *bm){  void ogl_freebmtexture(grs_bitmap *bm){
  if (bm->gltexture>=0){   if (bm->gltexture){
  r_texcount--;   ogl_freetexture(bm->gltexture);
  mprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));   bm->gltexture=NULL;
  glDeleteTextures( 1, &bm->gltexture );  // r_texcount--;
  bm->gltexture=-1;  // mprintf((0,"ogl_freebmtexture(%p,%p):%i (%i left)\n",bm->bm_data,&bm->gltexture,bm->gltexture,r_texcount));
   // glDeleteTextures( 1, &bm->gltexture );
   // bm->gltexture=-1;
  }   }
 }  }

Legend:
line(s) removed in v.1.12 
line(s) changed
 line(s) added in v.1.13