1 /* Emacs style mode select   -*- C++ -*-
2  *-----------------------------------------------------------------------------
3  *
4  *
5  *  PrBoom: a Doom port merged with LxDoom and LSDLDoom
6  *  based on BOOM, a modified and improved DOOM engine
7  *  Copyright (C) 1999 by
8  *  id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9  *  Copyright (C) 1999-2000 by
10  *  Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11  *  Copyright 2005, 2006 by
12  *  Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13  *
14  *  This program is free software; you can redistribute it and/or
15  *  modify it under the terms of the GNU General Public License
16  *  as published by the Free Software Foundation; either version 2
17  *  of the License, or (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  *  02111-1307, USA.
28  *
29  * DESCRIPTION:
30  *
31  *---------------------------------------------------------------------
32  */
33 
34 #include "z_zone.h"
35 #ifdef _WIN32
36 #define WIN32_LEAN_AND_MEAN
37 #include <windows.h>
38 #endif
39 #ifndef CALLBACK
40 #define CALLBACK
41 #endif
42 #include <stdio.h>
43 #include <string.h>
44 #include <math.h>
45 #include <SDL.h>
46 #include <SDL_opengl.h>
47 #include "doomtype.h"
48 #include "w_wad.h"
49 #include "m_argv.h"
50 #include "d_event.h"
51 #include "v_video.h"
52 #include "doomstat.h"
53 #include "r_bsp.h"
54 #include "r_main.h"
55 #include "r_draw.h"
56 #include "r_sky.h"
57 #include "r_plane.h"
58 #include "r_data.h"
59 #include "p_maputl.h"
60 #include "p_tick.h"
61 #include "m_bbox.h"
62 #include "lprintf.h"
63 #include "gl_intern.h"
64 #include "gl_struct.h"
65 
66 /* TEXTURES */
67 static GLTexture **gld_GLTextures=NULL;
68 /* PATCHES FLATS SPRITES */
69 static GLTexture **gld_GLPatchTextures=NULL;
70 
71 boolean use_mipmapping=false;
72 
73 int gld_max_texturesize=0;
74 char *gl_tex_format_string;
75 //int gl_tex_format=GL_RGBA8;
76 int gl_tex_format=GL_RGB5_A1;
77 //int gl_tex_format=GL_RGBA4;
78 //int gl_tex_format=GL_RGBA2;
79 
80 GLTexture *last_gltexture=NULL;
81 int last_cm=-1;
82 
83 int transparent_pal_index;
84 unsigned char gld_palmap[256];
85 
gld_InitPalettedTextures(void)86 void gld_InitPalettedTextures(void)
87 {
88   const unsigned char *playpal;
89   int pal[256];
90   int i,j;
91 
92   playpal=W_CacheLumpName("PLAYPAL");
93   for (i=0; i<256; i++) {
94     pal[i] = (playpal[i*3+0] << 16) | (playpal[i*3+1] << 8) | playpal[i*3+2];
95     gld_palmap[i] = i;
96   }
97   transparent_pal_index = -1;
98   for (i=0; i<256; i++) {
99     for (j=i+1; j<256; j++) {
100       if (pal[i] == pal[j]) {
101         transparent_pal_index = j;
102         gld_palmap[j] = i;
103         break;
104       }
105     }
106     if (transparent_pal_index >= 0)
107       break;
108   }
109   W_UnlockLumpName("PLAYPAL");
110 }
111 
gld_GetTexDimension(int value)112 int gld_GetTexDimension(int value)
113 {
114   int i;
115 
116   i=1;
117   while (i<value)
118     i*=2;
119   if (i>gld_max_texturesize)
120     i=gld_max_texturesize;
121   return i;
122 }
123 
gld_AddNewGLTexture(int texture_num)124 static GLTexture *gld_AddNewGLTexture(int texture_num)
125 {
126   if (texture_num<0)
127     return NULL;
128   if (texture_num>=numtextures)
129     return NULL;
130   if (!gld_GLTextures)
131   {
132     gld_GLTextures=Z_Malloc(numtextures*sizeof(GLTexture *),PU_STATIC,0);
133     memset(gld_GLTextures,0,numtextures*sizeof(GLTexture *));
134   }
135   if (!gld_GLTextures[texture_num])
136   {
137     gld_GLTextures[texture_num]=Z_Malloc(sizeof(GLTexture),PU_STATIC,0);
138     memset(gld_GLTextures[texture_num], 0, sizeof(GLTexture));
139     gld_GLTextures[texture_num]->textype=GLDT_UNREGISTERED;
140   }
141   return gld_GLTextures[texture_num];
142 }
143 
gld_AddNewGLPatchTexture(int lump)144 static GLTexture *gld_AddNewGLPatchTexture(int lump)
145 {
146   if (lump<0)
147     return NULL;
148   if (lump>=numlumps)
149     return NULL;
150   if (!gld_GLPatchTextures)
151   {
152     gld_GLPatchTextures=Z_Malloc(numlumps*sizeof(GLTexture *),PU_STATIC,0);
153     memset(gld_GLPatchTextures,0,numlumps*sizeof(GLTexture *));
154   }
155   if (!gld_GLPatchTextures[lump])
156   {
157     gld_GLPatchTextures[lump]=Z_Malloc(sizeof(GLTexture),PU_STATIC,0);
158     memset(gld_GLPatchTextures[lump], 0, sizeof(GLTexture));
159     gld_GLPatchTextures[lump]->textype=GLDT_UNREGISTERED;
160   }
161   return gld_GLPatchTextures[lump];
162 }
163 
gld_SetTexturePalette(GLenum target)164 void gld_SetTexturePalette(GLenum target)
165 {
166   const unsigned char *playpal;
167   unsigned char pal[1024];
168   int i;
169 
170   playpal=W_CacheLumpName("PLAYPAL");
171   for (i=0; i<256; i++) {
172     pal[i*4+0] = playpal[i*3+0];
173     pal[i*4+1] = playpal[i*3+1];
174     pal[i*4+2] = playpal[i*3+2];
175     pal[i*4+3] = 255;
176   }
177   pal[transparent_pal_index*4+0]=0;
178   pal[transparent_pal_index*4+1]=0;
179   pal[transparent_pal_index*4+2]=0;
180   pal[transparent_pal_index*4+3]=0;
181   gld_ColorTableEXT(target, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, pal);
182   W_UnlockLumpName("PLAYPAL");
183 }
184 
gld_AddPatchToTexture_UnTranslated(GLTexture * gltexture,unsigned char * buffer,const rpatch_t * patch,int originx,int originy,int paletted)185 static void gld_AddPatchToTexture_UnTranslated(GLTexture *gltexture, unsigned char *buffer, const rpatch_t *patch, int originx, int originy, int paletted)
186 {
187   int x,y,j;
188   int xs,xe;
189   int js,je;
190   const rcolumn_t *column;
191   const byte *source;
192   int i, pos;
193   const unsigned char *playpal;
194 
195   if (!gltexture)
196     return;
197   if (!patch)
198     return;
199   playpal=W_CacheLumpName("PLAYPAL");
200   xs=0;
201   xe=patch->width;
202   if ((xs+originx)>=gltexture->realtexwidth)
203     return;
204   if ((xe+originx)<=0)
205     return;
206   if ((xs+originx)<0)
207     xs=-originx;
208   if ((xe+originx)>gltexture->realtexwidth)
209     xe+=(gltexture->realtexwidth-(xe+originx));
210   for (x=xs;x<xe;x++)
211   {
212 #ifdef RANGECHECK
213     if (x>=patch->width)
214     {
215       lprintf(LO_ERROR,"gld_AddPatchToTexture_UnTranslated x>=patch->width (%i >= %i)\n",x,patch->width);
216       return;
217     }
218 #endif
219     column = &patch->columns[x];
220     for (i=0; i<column->numPosts; i++) {
221       const rpost_t *post = &column->posts[i];
222       y=(post->topdelta+originy);
223       js=0;
224       je=post->length;
225       if ((js+y)>=gltexture->realtexheight)
226         continue;
227       if ((je+y)<=0)
228         continue;
229       if ((js+y)<0)
230         js=-y;
231       if ((je+y)>gltexture->realtexheight)
232         je+=(gltexture->realtexheight-(je+y));
233       source = column->pixels + post->topdelta;
234       if (paletted) {
235         pos=(((js+y)*gltexture->buffer_width)+x+originx);
236         for (j=js;j<je;j++,pos+=(gltexture->buffer_width))
237         {
238 #ifdef RANGECHECK
239           if (pos>=gltexture->buffer_size)
240           {
241             lprintf(LO_ERROR,"gld_AddPatchToTexture_UnTranslated pos>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
242             return;
243           }
244 #endif
245           buffer[pos]=gld_palmap[source[j]];
246         }
247       } else {
248         pos=4*(((js+y)*gltexture->buffer_width)+x+originx);
249         for (j=js;j<je;j++,pos+=(4*gltexture->buffer_width))
250         {
251 #ifdef RANGECHECK
252           if ((pos+3)>=gltexture->buffer_size)
253           {
254             lprintf(LO_ERROR,"gld_AddPatchToTexture_UnTranslated pos+3>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
255             return;
256           }
257 #endif
258           buffer[pos]=playpal[source[j]*3];
259           buffer[pos+1]=playpal[source[j]*3+1];
260           buffer[pos+2]=playpal[source[j]*3+2];
261           buffer[pos+3]=255;
262         }
263       }
264     }
265   }
266   W_UnlockLumpName("PLAYPAL");
267 }
268 
gld_AddPatchToTexture(GLTexture * gltexture,unsigned char * buffer,const rpatch_t * patch,int originx,int originy,int cm,int paletted)269 void gld_AddPatchToTexture(GLTexture *gltexture, unsigned char *buffer, const rpatch_t *patch, int originx, int originy, int cm, int paletted)
270 {
271   int x,y,j;
272   int xs,xe;
273   int js,je;
274   const rcolumn_t *column;
275   const byte *source;
276   int i, pos;
277   const unsigned char *playpal;
278   const unsigned char *outr;
279 
280   if (!gltexture)
281     return;
282   if (!patch)
283     return;
284   if ((cm==CR_DEFAULT) || (cm==CR_LIMIT))
285   {
286     gld_AddPatchToTexture_UnTranslated(gltexture,buffer,patch,originx,originy, paletted);
287     return;
288   }
289   if (cm<CR_LIMIT)
290     outr=colrngs[cm];
291   else
292     outr=translationtables + 256*((cm-CR_LIMIT)-1);
293   playpal=W_CacheLumpName("PLAYPAL");
294   xs=0;
295   xe=patch->width;
296   if ((xs+originx)>=gltexture->realtexwidth)
297     return;
298   if ((xe+originx)<=0)
299     return;
300   if ((xs+originx)<0)
301     xs=-originx;
302   if ((xe+originx)>gltexture->realtexwidth)
303     xe+=(gltexture->realtexwidth-(xe+originx));
304   for (x=xs;x<xe;x++)
305   {
306 #ifdef RANGECHECK
307     if (x>=patch->width)
308     {
309       lprintf(LO_ERROR,"gld_AddPatchToTexture x>=patch->width (%i >= %i)\n",x,patch->width);
310       return;
311     }
312 #endif
313     column = &patch->columns[x];
314     for (i=0; i<column->numPosts; i++) {
315       const rpost_t *post = &column->posts[i];
316       y=(post->topdelta+originy);
317       js=0;
318       je=post->length;
319       if ((js+y)>=gltexture->realtexheight)
320         continue;
321       if ((je+y)<=0)
322         continue;
323       if ((js+y)<0)
324         js=-y;
325       if ((je+y)>gltexture->realtexheight)
326         je+=(gltexture->realtexheight-(je+y));
327       source = column->pixels + post->topdelta;
328       if (paletted) {
329         pos=(((js+y)*gltexture->buffer_width)+x+originx);
330         for (j=js;j<je;j++,pos+=(gltexture->buffer_width))
331         {
332 #ifdef RANGECHECK
333           if (pos>=gltexture->buffer_size)
334           {
335             lprintf(LO_ERROR,"gld_AddPatchToTexture_UnTranslated pos>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
336             return;
337           }
338 #endif
339           buffer[pos]=gld_palmap[outr[source[j]]];
340         }
341       } else {
342         pos=4*(((js+y)*gltexture->buffer_width)+x+originx);
343         for (j=js;j<je;j++,pos+=(4*gltexture->buffer_width))
344         {
345 #ifdef RANGECHECK
346           if ((pos+3)>=gltexture->buffer_size)
347           {
348             lprintf(LO_ERROR,"gld_AddPatchToTexture pos+3>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
349             return;
350           }
351 #endif
352           buffer[pos]=playpal[outr[source[j]]*3];
353           buffer[pos+1]=playpal[outr[source[j]]*3+1];
354           buffer[pos+2]=playpal[outr[source[j]]*3+2];
355           buffer[pos+3]=255;
356         }
357       }
358     }
359   }
360   W_UnlockLumpName("PLAYPAL");
361 }
362 
gld_AddFlatToTexture(GLTexture * gltexture,unsigned char * buffer,const unsigned char * flat,int paletted)363 static void gld_AddFlatToTexture(GLTexture *gltexture, unsigned char *buffer, const unsigned char *flat, int paletted)
364 {
365   int x,y,pos;
366   const unsigned char *playpal;
367 
368   if (!gltexture)
369     return;
370   if (!flat)
371     return;
372   if (paletted) {
373     for (y=0;y<gltexture->realtexheight;y++)
374     {
375       pos=(y*gltexture->buffer_width);
376       for (x=0;x<gltexture->realtexwidth;x++,pos++)
377       {
378 #ifdef RANGECHECK
379         if (pos>=gltexture->buffer_size)
380         {
381           lprintf(LO_ERROR,"gld_AddFlatToTexture pos>=size (%i >= %i)\n",pos,gltexture->buffer_size);
382           return;
383         }
384 #endif
385         buffer[pos]=gld_palmap[flat[y*64+x]];
386       }
387     }
388   } else {
389     playpal=W_CacheLumpName("PLAYPAL");
390     for (y=0;y<gltexture->realtexheight;y++)
391     {
392       pos=4*(y*gltexture->buffer_width);
393       for (x=0;x<gltexture->realtexwidth;x++,pos+=4)
394       {
395 #ifdef RANGECHECK
396         if ((pos+3)>=gltexture->buffer_size)
397         {
398           lprintf(LO_ERROR,"gld_AddFlatToTexture pos+3>=size (%i >= %i)\n",pos+3,gltexture->buffer_size);
399           return;
400         }
401 #endif
402         buffer[pos]=playpal[flat[y*64+x]*3];
403         buffer[pos+1]=playpal[flat[y*64+x]*3+1];
404         buffer[pos+2]=playpal[flat[y*64+x]*3+2];
405         buffer[pos+3]=255;
406       }
407     }
408     W_UnlockLumpName("PLAYPAL");
409   }
410 }
411 
412 //e6y: "force" flag for loading texture with zero index
gld_RegisterTexture(int texture_num,boolean mipmap,boolean force)413 GLTexture *gld_RegisterTexture(int texture_num, boolean mipmap, boolean force)
414 {
415   GLTexture *gltexture;
416 
417   //e6y: textures with zero index should be loaded sometimes
418   if (texture_num==NO_TEXTURE && !force)
419     return NULL;
420   gltexture=gld_AddNewGLTexture(texture_num);
421   if (!gltexture)
422     return NULL;
423   if (gltexture->textype==GLDT_UNREGISTERED)
424   {
425     texture_t *texture=NULL;
426 
427     if ((texture_num>=0) || (texture_num<numtextures))
428       texture=textures[texture_num];
429     if (!texture)
430       return NULL;
431     gltexture->textype=GLDT_BROKEN;
432     gltexture->index=texture_num;
433     gltexture->mipmap=mipmap;
434     gltexture->realtexwidth=texture->width;
435     gltexture->realtexheight=texture->height;
436     gltexture->leftoffset=0;
437     gltexture->topoffset=0;
438     gltexture->tex_width=gld_GetTexDimension(gltexture->realtexwidth);
439     gltexture->tex_height=gld_GetTexDimension(gltexture->realtexheight);
440     gltexture->width=MIN(gltexture->realtexwidth, gltexture->tex_width);
441     gltexture->height=MIN(gltexture->realtexheight, gltexture->tex_height);
442     gltexture->buffer_width=gltexture->tex_width;
443     gltexture->buffer_height=gltexture->tex_height;
444 #ifdef USE_GLU_IMAGESCALE
445     gltexture->width=gltexture->tex_width;
446     gltexture->height=gltexture->tex_height;
447     gltexture->buffer_width=gltexture->realtexwidth;
448     gltexture->buffer_height=gltexture->realtexheight;
449 #endif
450     if (gltexture->mipmap & use_mipmapping)
451     {
452       gltexture->width=gltexture->tex_width;
453       gltexture->height=gltexture->tex_height;
454       gltexture->buffer_width=gltexture->realtexwidth;
455       gltexture->buffer_height=gltexture->realtexheight;
456     }
457     gltexture->buffer_size=gltexture->buffer_width*gltexture->buffer_height*4;
458     if (gltexture->realtexwidth>gltexture->buffer_width)
459       return gltexture;
460     if (gltexture->realtexheight>gltexture->buffer_height)
461       return gltexture;
462     gltexture->textype=GLDT_TEXTURE;
463   }
464   return gltexture;
465 }
466 
gld_BindTexture(GLTexture * gltexture)467 void gld_BindTexture(GLTexture *gltexture)
468 {
469   const rpatch_t *patch;
470   int i;
471   unsigned char *buffer;
472 
473   if (gltexture==last_gltexture)
474     return;
475   last_gltexture=gltexture;
476   if (!gltexture) {
477     glBindTexture(GL_TEXTURE_2D, 0);
478     last_gltexture = NULL;
479     last_cm = -1;
480     return;
481   }
482   if (gltexture->textype!=GLDT_TEXTURE)
483   {
484     glBindTexture(GL_TEXTURE_2D, 0);
485     last_gltexture = NULL;
486     last_cm = -1;
487     return;
488   }
489   if (gltexture->glTexID[CR_DEFAULT]!=0)
490   {
491     glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]);
492     glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_RESIDENT,&i);
493 #ifdef _DEBUG
494     if (i!=GL_TRUE)
495       lprintf(LO_INFO, "glGetTexParam: %i\n", i);
496 #endif
497     if (i==GL_TRUE)
498       return;
499   }
500   buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0);
501   if (!(gltexture->mipmap & use_mipmapping) & gl_paletted_texture)
502     memset(buffer,transparent_pal_index,gltexture->buffer_size);
503   else
504     memset(buffer,0,gltexture->buffer_size);
505   patch=R_CacheTextureCompositePatchNum(gltexture->index);
506   gld_AddPatchToTexture(gltexture, buffer, patch,
507                         0, 0,
508                         CR_DEFAULT, !(gltexture->mipmap & use_mipmapping) & gl_paletted_texture);
509   R_UnlockTextureCompositePatchNum(gltexture->index);
510   if (gltexture->glTexID[CR_DEFAULT]==0)
511     glGenTextures(1,&gltexture->glTexID[CR_DEFAULT]);
512   glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]);
513 #ifdef USE_GLU_MIPMAP
514   if (gltexture->mipmap & use_mipmapping)
515   {
516     gluBuild2DMipmaps(GL_TEXTURE_2D, gl_tex_format,
517                       gltexture->buffer_width, gltexture->buffer_height,
518                       GL_RGBA, GL_UNSIGNED_BYTE, buffer);
519     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
520     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
521     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
522     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_mipmap_filter);
523     if (gl_texture_filter_anisotropic)
524       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0);
525   }
526   else
527 #endif /* USE_GLU_MIPMAP */
528   {
529 #ifdef USE_GLU_IMAGESCALE
530     if ((gltexture->buffer_width!=gltexture->tex_width) ||
531         (gltexture->buffer_height!=gltexture->tex_height)
532        )
533     {
534       unsigned char *scaledbuffer;
535 
536       scaledbuffer=(unsigned char*)Z_Malloc(gltexture->tex_width*gltexture->tex_height*4,PU_STATIC,0);
537       if (scaledbuffer)
538       {
539         gluScaleImage(GL_RGBA,
540                       gltexture->buffer_width, gltexture->buffer_height,
541                       GL_UNSIGNED_BYTE,buffer,
542                       gltexture->tex_width, gltexture->tex_height,
543                       GL_UNSIGNED_BYTE,scaledbuffer);
544         Z_Free(buffer);
545         buffer=scaledbuffer;
546         glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
547                       gltexture->tex_width, gltexture->tex_height,
548                       0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
549       }
550     }
551     else
552 #endif /* USE_GLU_IMAGESCALE */
553     {
554       if (gl_paletted_texture) {
555         gld_SetTexturePalette(GL_TEXTURE_2D);
556         glTexImage2D( GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
557                       gltexture->buffer_width, gltexture->buffer_height,
558                       0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buffer);
559       } else {
560         glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
561                       gltexture->buffer_width, gltexture->buffer_height,
562                       0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
563       }
564     }
565     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
566     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
567     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
568     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter);
569   }
570   Z_Free(buffer);
571 }
572 
gld_RegisterPatch(int lump,int cm)573 GLTexture *gld_RegisterPatch(int lump, int cm)
574 {
575   const rpatch_t *patch;
576   GLTexture *gltexture;
577 
578   gltexture=gld_AddNewGLPatchTexture(lump);
579   if (!gltexture)
580     return NULL;
581   if (gltexture->textype==GLDT_UNREGISTERED)
582   {
583     patch=R_CachePatchNum(lump);
584     if (!patch)
585       return NULL;
586     gltexture->textype=GLDT_BROKEN;
587     gltexture->index=lump;
588     gltexture->mipmap=false;
589     gltexture->realtexwidth=patch->width;
590     gltexture->realtexheight=patch->height;
591     gltexture->leftoffset=patch->leftoffset;
592     gltexture->topoffset=patch->topoffset;
593     gltexture->tex_width=gld_GetTexDimension(gltexture->realtexwidth);
594     gltexture->tex_height=gld_GetTexDimension(gltexture->realtexheight);
595     gltexture->width=MIN(gltexture->realtexwidth, gltexture->tex_width);
596     gltexture->height=MIN(gltexture->realtexheight, gltexture->tex_height);
597     gltexture->buffer_width=gltexture->tex_width;
598     gltexture->buffer_height=gltexture->tex_height;
599 #ifdef USE_GLU_IMAGESCALE
600     gltexture->width=MIN(gltexture->realtexwidth, gltexture->tex_width);
601     gltexture->height=MIN(gltexture->realtexheight, gltexture->tex_height);
602     gltexture->buffer_width=MAX(gltexture->realtexwidth, gltexture->tex_width);
603     gltexture->buffer_height=MAX(gltexture->realtexheight, gltexture->tex_height);
604 #endif
605     gltexture->buffer_size=gltexture->buffer_width*gltexture->buffer_height*4;
606     R_UnlockPatchNum(lump);
607     if (gltexture->realtexwidth>gltexture->buffer_width)
608       return gltexture;
609     if (gltexture->realtexheight>gltexture->buffer_height)
610       return gltexture;
611     gltexture->textype=GLDT_PATCH;
612   }
613   return gltexture;
614 }
615 
gld_BindPatch(GLTexture * gltexture,int cm)616 void gld_BindPatch(GLTexture *gltexture, int cm)
617 {
618   const rpatch_t *patch;
619   int i;
620   unsigned char *buffer;
621 
622   if ((gltexture==last_gltexture) && (cm==last_cm))
623     return;
624   last_gltexture=gltexture;
625   last_cm=cm;
626   if (!gltexture)
627     return;
628   if (gltexture->textype!=GLDT_PATCH)
629   {
630     glBindTexture(GL_TEXTURE_2D, 0);
631     last_gltexture = NULL;
632     last_cm = -1;
633     return;
634   }
635   if (gltexture->glTexID[cm]!=0)
636   {
637     glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[cm]);
638     glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_RESIDENT,&i);
639 #ifdef _DEBUG
640     if (i!=GL_TRUE)
641       lprintf(LO_INFO, "glGetTexParam: %i\n", i);
642 #endif
643     if (i==GL_TRUE)
644       return;
645   }
646   patch=R_CachePatchNum(gltexture->index);
647   buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0);
648   if (gl_paletted_texture)
649     memset(buffer,transparent_pal_index,gltexture->buffer_size);
650   else
651     memset(buffer,0,gltexture->buffer_size);
652   gld_AddPatchToTexture(gltexture, buffer, patch, 0, 0, cm, gl_paletted_texture);
653   if (gltexture->glTexID[cm]==0)
654     glGenTextures(1,&gltexture->glTexID[cm]);
655   glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[cm]);
656 #ifdef USE_GLU_IMAGESCALE
657   if ((gltexture->buffer_width>gltexture->tex_width) ||
658       (gltexture->buffer_height>gltexture->tex_height)
659      )
660   {
661     unsigned char *scaledbuffer;
662 
663     scaledbuffer=(unsigned char*)Z_Malloc(gltexture->tex_width*gltexture->tex_height*4,PU_STATIC,0);
664     if (scaledbuffer)
665     {
666       gluScaleImage(GL_RGBA,
667                     gltexture->buffer_width, gltexture->buffer_height,
668                     GL_UNSIGNED_BYTE,buffer,
669                     gltexture->tex_width, gltexture->tex_height,
670                     GL_UNSIGNED_BYTE,scaledbuffer);
671       Z_Free(buffer);
672       buffer=scaledbuffer;
673       glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
674                     gltexture->tex_width, gltexture->tex_height,
675                     0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
676     }
677   }
678   else
679 #endif /* USE_GLU_IMAGESCALE */
680   {
681       if (gl_paletted_texture) {
682         gld_SetTexturePalette(GL_TEXTURE_2D);
683         glTexImage2D( GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
684                       gltexture->buffer_width, gltexture->buffer_height,
685                       0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buffer);
686       } else {
687         glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
688                       gltexture->buffer_width, gltexture->buffer_height,
689                       0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
690       }
691   }
692   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
693   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
694   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
695   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter);
696   Z_Free(buffer);
697   R_UnlockPatchNum(gltexture->index);
698 }
699 
gld_RegisterFlat(int lump,boolean mipmap)700 GLTexture *gld_RegisterFlat(int lump, boolean mipmap)
701 {
702   GLTexture *gltexture;
703 
704   gltexture=gld_AddNewGLPatchTexture(firstflat+lump);
705   if (!gltexture)
706     return NULL;
707   if (gltexture->textype==GLDT_UNREGISTERED)
708   {
709     gltexture->textype=GLDT_BROKEN;
710     gltexture->index=firstflat+lump;
711     gltexture->mipmap=mipmap;
712     gltexture->realtexwidth=64;
713     gltexture->realtexheight=64;
714     gltexture->leftoffset=0;
715     gltexture->topoffset=0;
716     gltexture->tex_width=gld_GetTexDimension(gltexture->realtexwidth);
717     gltexture->tex_height=gld_GetTexDimension(gltexture->realtexheight);
718     gltexture->width=MIN(gltexture->realtexwidth, gltexture->tex_width);
719     gltexture->height=MIN(gltexture->realtexheight, gltexture->tex_height);
720     gltexture->buffer_width=gltexture->tex_width;
721     gltexture->buffer_height=gltexture->tex_height;
722 #ifdef USE_GLU_IMAGESCALE
723     gltexture->width=gltexture->tex_width;
724     gltexture->height=gltexture->tex_height;
725     gltexture->buffer_width=gltexture->realtexwidth;
726     gltexture->buffer_height=gltexture->realtexheight;
727 #endif
728     if (gltexture->mipmap & use_mipmapping)
729     {
730       gltexture->width=gltexture->tex_width;
731       gltexture->height=gltexture->tex_height;
732       gltexture->buffer_width=gltexture->realtexwidth;
733       gltexture->buffer_height=gltexture->realtexheight;
734     }
735     gltexture->buffer_size=gltexture->buffer_width*gltexture->buffer_height*4;
736     if (gltexture->realtexwidth>gltexture->buffer_width)
737       return gltexture;
738     if (gltexture->realtexheight>gltexture->buffer_height)
739       return gltexture;
740     gltexture->textype=GLDT_FLAT;
741   }
742   return gltexture;
743 }
744 
gld_BindFlat(GLTexture * gltexture)745 void gld_BindFlat(GLTexture *gltexture)
746 {
747   const unsigned char *flat;
748   int i;
749   unsigned char *buffer;
750 
751   if (gltexture==last_gltexture)
752     return;
753   last_gltexture=gltexture;
754   if (!gltexture)
755     return;
756   if (gltexture->textype!=GLDT_FLAT)
757   {
758     glBindTexture(GL_TEXTURE_2D, 0);
759     last_gltexture = NULL;
760     last_cm = -1;
761     return;
762   }
763   if (gltexture->glTexID[CR_DEFAULT]!=0)
764   {
765     glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]);
766     glGetTexParameteriv(GL_TEXTURE_2D,GL_TEXTURE_RESIDENT,&i);
767 #ifdef _DEBUG
768     if (i!=GL_TRUE)
769       lprintf(LO_INFO, "glGetTexParam: %i\n", i);
770 #endif
771     if (i==GL_TRUE)
772       return;
773   }
774   flat=W_CacheLumpNum(gltexture->index);
775   buffer=(unsigned char*)Z_Malloc(gltexture->buffer_size,PU_STATIC,0);
776   if (!(gltexture->mipmap & use_mipmapping) & gl_paletted_texture)
777     memset(buffer,transparent_pal_index,gltexture->buffer_size);
778   else
779     memset(buffer,0,gltexture->buffer_size);
780   gld_AddFlatToTexture(gltexture, buffer, flat, !(gltexture->mipmap & use_mipmapping) & gl_paletted_texture);
781   if (gltexture->glTexID[CR_DEFAULT]==0)
782     glGenTextures(1,&gltexture->glTexID[CR_DEFAULT]);
783   glBindTexture(GL_TEXTURE_2D, gltexture->glTexID[CR_DEFAULT]);
784 #ifdef USE_GLU_MIPMAP
785   if (gltexture->mipmap & use_mipmapping)
786   {
787     gluBuild2DMipmaps(GL_TEXTURE_2D, gl_tex_format,
788                       gltexture->buffer_width, gltexture->buffer_height,
789                       GL_RGBA, GL_UNSIGNED_BYTE, buffer);
790     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
791     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
792     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
793     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_mipmap_filter);
794     if (gl_texture_filter_anisotropic)
795       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0);
796   }
797   else
798 #endif /* USE_GLU_MIPMAP */
799   {
800 #ifdef USE_GLU_IMAGESCALE
801     if ((gltexture->buffer_width!=gltexture->tex_width) ||
802         (gltexture->buffer_height!=gltexture->tex_height)
803        )
804     {
805       unsigned char *scaledbuffer;
806 
807       scaledbuffer=(unsigned char*)Z_Malloc(gltexture->tex_width*gltexture->tex_height*4,PU_STATIC,0);
808       if (scaledbuffer)
809       {
810         gluScaleImage(GL_RGBA,
811                       gltexture->buffer_width, gltexture->buffer_height,
812                       GL_UNSIGNED_BYTE,buffer,
813                       gltexture->tex_width, gltexture->tex_height,
814                       GL_UNSIGNED_BYTE,scaledbuffer);
815         Z_Free(buffer);
816         buffer=scaledbuffer;
817         glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
818                       gltexture->tex_width, gltexture->tex_height,
819                       0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
820       }
821     }
822     else
823 #endif /* USE_GLU_IMAGESCALE */
824     {
825       if (gl_paletted_texture) {
826         gld_SetTexturePalette(GL_TEXTURE_2D);
827         glTexImage2D( GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT,
828                       gltexture->buffer_width, gltexture->buffer_height,
829                       0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, buffer);
830       } else {
831         glTexImage2D( GL_TEXTURE_2D, 0, gl_tex_format,
832                       gltexture->buffer_width, gltexture->buffer_height,
833                       0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
834       }
835     }
836     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
837     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
838     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_filter);
839     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_filter);
840   }
841   Z_Free(buffer);
842   W_UnlockLumpNum(gltexture->index);
843 }
844 
gld_CleanTextures(void)845 static void gld_CleanTextures(void)
846 {
847   int i,j;
848 
849   if (!gld_GLTextures)
850     return;
851   for (i=0; i<numtextures; i++)
852   {
853     if (gld_GLTextures[i])
854     {
855       for (j=0; j<(CR_LIMIT+MAXPLAYERS); j++)
856         glDeleteTextures(1,&(gld_GLTextures[i]->glTexID[j]));
857       Z_Free(gld_GLTextures[i]);
858     }
859   }
860   memset(gld_GLTextures,0,numtextures*sizeof(GLTexture *));
861 }
862 
gld_CleanPatchTextures(void)863 static void gld_CleanPatchTextures(void)
864 {
865   int i,j;
866 
867   if (!gld_GLPatchTextures)
868     return;
869   for (i=0; i<numlumps; i++)
870   {
871     if (gld_GLPatchTextures[i])
872     {
873       for (j=0; j<(CR_LIMIT+MAXPLAYERS); j++)
874         glDeleteTextures(1,&(gld_GLPatchTextures[i]->glTexID[j]));
875       Z_Free(gld_GLPatchTextures[i]);
876     }
877   }
878   memset(gld_GLPatchTextures,0,numlumps*sizeof(GLTexture *));
879 }
880 
gld_Precache(void)881 void gld_Precache(void)
882 {
883   register int i;
884   register byte *hitlist;
885 
886   if (demoplayback)
887     return;
888 
889   {
890     size_t size = numflats > numsprites  ? numflats : numsprites;
891     hitlist = Z_Malloc((size_t)numtextures > size ? numtextures : size,PU_LEVEL,0);
892   }
893 
894   // Precache flats.
895 
896   memset(hitlist, 0, numflats);
897 
898   for (i = numsectors; --i >= 0; )
899     hitlist[sectors[i].floorpic] = hitlist[sectors[i].ceilingpic] = 1;
900 
901   for (i = numflats; --i >= 0; )
902     if (hitlist[i])
903       gld_BindFlat(gld_RegisterFlat(i,true));
904 
905   // Precache textures.
906 
907   memset(hitlist, 0, numtextures);
908 
909   for (i = numsides; --i >= 0;)
910     hitlist[sides[i].bottomtexture] =
911       hitlist[sides[i].toptexture] =
912       hitlist[sides[i].midtexture] = 1;
913 
914   // Sky texture is always present.
915   // Note that F_SKY1 is the name used to
916   //  indicate a sky floor/ceiling as a flat,
917   //  while the sky texture is stored like
918   //  a wall texture, with an episode dependend
919   //  name.
920 
921   hitlist[skytexture] = 0;
922 
923   for (i = numtextures; --i >= 0; )
924     if (hitlist[i])
925       gld_BindTexture(gld_RegisterTexture(i,true,false));
926 
927   // Precache sprites.
928   memset(hitlist, 0, numsprites);
929 
930   {
931     thinker_t *th;
932     for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
933       if (th->function == P_MobjThinker)
934         hitlist[((mobj_t *)th)->sprite] = 1;
935   }
936 
937   for (i=numsprites; --i >= 0;)
938     if (hitlist[i])
939       {
940         int j = sprites[i].numframes;
941         while (--j >= 0)
942           {
943             short *sflump = sprites[i].spriteframes[j].lump;
944             int k = 7;
945             do
946               gld_BindPatch(gld_RegisterPatch(firstspritelump + sflump[k],CR_DEFAULT),CR_DEFAULT);
947             while (--k >= 0);
948           }
949       }
950   Z_Free(hitlist);
951 }
952 
gld_CleanMemory(void)953 void gld_CleanMemory(void)
954 {
955   gld_CleanTextures();
956   gld_CleanPatchTextures();
957 }
958