]> icculus.org git repositories - theoddone33/hheretic.git/blob - opengl/ogl_tex.c
Initial revision
[theoddone33/hheretic.git] / opengl / ogl_tex.c
1
2 //**************************************************************************
3 //**
4 //** OGL_TEX.C
5 //**
6 //**************************************************************************
7
8 // HEADER FILES ------------------------------------------------------------
9
10 #ifdef __WIN32
11 #define WIN32_LEAN_AND_MEAN
12 #include <windows.h>
13 #endif
14
15 #include <stdlib.h>
16 #include <GL/gl.h>
17 #include <GL/glu.h>
18 #include "doomdef.h"
19 #include "r_local.h"
20 #include "ogl_def.h"
21
22 // MACROS ------------------------------------------------------------------
23
24 // TYPES -------------------------------------------------------------------
25
26 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
27
28 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
29
30 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
31
32 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
33
34                                 
35 extern int numtextures;
36 extern texture_t** textures;
37
38 int mipmapping = 0;
39 int linearRaw = 0;
40 extern int maxTexSize;          // Maximum supported texture size.
41 extern int ratioLimit;
42 extern int test3dfx;
43
44 // PUBLIC DATA DEFINITIONS -------------------------------------------------
45
46 int pallump;
47
48 // Properties of the current texture.
49 float   texw=1, texh=1;
50 int             texmask=0;      
51 GLuint  curtex = 0;
52 byte    topLineRGB[3];
53
54 texsize_t *lumptexsizes;        // Sizes for all the lumps. 
55 unsigned short *spriteheights;
56
57 // PRIVATE DATA DEFINITIONS ------------------------------------------------
58
59 // Texture names for all lumps. Although the list will contain names for 
60 // ALL lumps, only the graphics entries that aren't flats, wall textures or 
61 // sprites are used.
62 static GLuint *lumptexnames, *lumptexnames2;    // Support for two parts.
63 static int *rawlumps, numrawlumps;      // Raw screen lumps (just lump numbers).
64         
65 static GLuint *flattexnames, *texnames, *spritenames;
66 static char *texmasked;         // 1 if the texture is masked.
67 //static int total_texmem_used = 0;
68
69 static GLuint dltexname;        // Name of the dynamic light texture.
70
71 static int glmode[6] = // Indexed by 'mipmapping'.
72
73         GL_NEAREST,
74         GL_LINEAR,
75         GL_NEAREST_MIPMAP_NEAREST,
76         GL_LINEAR_MIPMAP_NEAREST,
77         GL_NEAREST_MIPMAP_LINEAR,
78         GL_LINEAR_MIPMAP_LINEAR
79 };
80
81
82 // CODE --------------------------------------------------------------------
83
84 int FindNextPower2(int num)
85 {
86         int cumul;
87         for(cumul=1; num > cumul; cumul *= 2);
88         return cumul;
89 }
90
91 float NextPower2Ratio(int num)
92 {
93         return num/(float)FindNextPower2(num);
94 }
95
96 void OGL_TexInit()
97 {
98         // Allocate memory for the flat texture numbers.
99         flattexnames = Z_Malloc(sizeof(GLuint)*numflats, PU_STATIC, 0); 
100         memset(flattexnames, 0, sizeof(GLuint)*numflats);
101
102         texnames = Z_Malloc(sizeof(GLuint)*numtextures, PU_STATIC, 0);
103         memset(texnames, 0, sizeof(GLuint)*numtextures);
104
105         texmasked = Z_Malloc(numtextures, PU_STATIC, 0);
106         memset(texmasked, 0, numtextures);
107
108         // Sprites.
109         spritenames = Z_Malloc(sizeof(GLuint)*numspritelumps, PU_STATIC, 0);
110         memset(spritenames, 0, sizeof(GLuint)*numspritelumps);  
111         spriteheights = Z_Malloc(sizeof(short)*numspritelumps, PU_STATIC, 0);
112         memset(spriteheights, 0, sizeof(short)*numspritelumps);
113
114         // Standard lump textures (raw images and other gfx).
115         // First parts.
116         lumptexnames = Z_Malloc(sizeof(GLuint)*numlumps, PU_STATIC, 0);
117         memset(lumptexnames, 0, sizeof(GLuint)*numlumps);
118         // Second parts.
119         lumptexnames2 = Z_Malloc(sizeof(GLuint)*numlumps, PU_STATIC, 0);
120         memset(lumptexnames2, 0, sizeof(GLuint)*numlumps);
121         // Size data.
122         lumptexsizes = Z_Malloc(sizeof(texsize_t)*numlumps, PU_STATIC, 0);
123         memset(lumptexsizes, 0, sizeof(texsize_t)*numlumps);
124
125         // Raw screen lump book keeping.
126         rawlumps = 0;
127         numrawlumps = 0;
128
129         // The dynamic light map.
130         dltexname = 0;
131
132         // The palette lump, for color information (really?).
133         pallump = W_GetNumForName("PLAYPAL");
134 }
135
136 void OGL_TexReset()
137 {
138         glDeleteTextures(numflats, flattexnames);
139         memset(flattexnames, 0, sizeof(GLuint)*numflats);
140
141         glDeleteTextures(numtextures, texnames);
142         memset(texnames, 0, sizeof(GLuint)*numtextures);
143         
144         memset(texmasked, 0, numtextures);
145
146         glDeleteTextures(numspritelumps, spritenames);
147         memset(spritenames, 0, sizeof(GLuint)*numspritelumps);
148         memset(spriteheights, 0, sizeof(short)*numspritelumps);
149
150 //      total_texmem_used = 0;
151
152         glDeleteTextures(1, &dltexname);
153         dltexname = 0;
154
155         // Normal patch/raw image textures aren't deleted here (see below).
156 }
157
158 void OGL_ResetLumpTexData()
159 {
160         glDeleteTextures(numlumps, lumptexnames);
161         glDeleteTextures(numlumps, lumptexnames2);
162         memset(lumptexnames, 0, sizeof(GLuint)*numlumps);
163         memset(lumptexnames2, 0, sizeof(GLuint)*numlumps);
164         memset(lumptexsizes, 0, sizeof(texsize_t)*numlumps);
165
166         // Free the raw lumps book keeping table.
167         free(rawlumps);
168         rawlumps = 0;
169         numrawlumps = 0;
170 }
171
172 // Binds the texture if necessary.
173 void OGL_BindTexture(GLuint texname)
174 {
175         if(curtex != texname) 
176         {
177                 glBindTexture(GL_TEXTURE_2D, texname);
178                 curtex = texname;
179         }
180 }
181
182 void PalToRGB(byte *palidx, byte *rgb)
183 {
184         int i;
185         for(i=0; i<3; i++) 
186         {
187                 *(rgb+i) = gammatable[usegamma][*(palidx+i)];
188         }
189 }
190
191 void PalIdxToRGB(byte *pal, int idx, byte *rgb)
192 {
193         PalToRGB(pal+idx*3, rgb);
194 }
195
196 unsigned int OGL_BindTexFlat(int lump)
197 {
198         GLuint name;
199         int p, i;
200         byte *flatptr = W_CacheLumpNum(lump, PU_STATIC);
201         byte *palette = W_CacheLumpNum(pallump=W_GetNumForName("PLAYPAL"), PU_CACHE);
202         byte *rgbflat = _alloca(3*lumpinfo[lump].size);
203         
204         if (lumpinfo[lump].size < 4096)
205         {
206                 printf ("Invalid Texture lump (%s,%d) found. Using texture 0\n",lumpinfo[lump].name, lump);
207                 OGL_BindTexture(0);
208                 return 0;
209         }
210
211         //printf( "OGL_SetFlat: Loading flat %d.\n",idx);
212         // Convert the data to RGB.
213         for(i=0, p=0; i<lumpinfo[lump].size; i++)
214                 PalIdxToRGB(palette, flatptr[i], rgbflat+i*3);
215
216         // Generate and bind the texture.
217         glGenTextures(1, &name);//flattexnames+idx);
218         glBindTexture(GL_TEXTURE_2D, name);//flattexnames[idx]);
219         
220         // Set the texture properties.
221         if(test3dfx)
222         {
223                 glTexImage2D(GL_TEXTURE_2D, 0, 3, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, rgbflat);
224         }
225         else {
226                 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 64, 64, GL_RGB, GL_UNSIGNED_BYTE, rgbflat);
227         }
228         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmapping]);
229         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
230
231         // Change the tag.
232         Z_ChangeTag(flatptr, PU_CACHE);
233         return name;
234 }
235
236 // Returns the OpenGL name of the texture.
237 unsigned int OGL_PrepareFlat(int idx)
238 {
239         idx = flattranslation[idx];
240         if(!flattexnames[idx])
241         {
242                 // The flat isn't yet bound with OpenGL.
243                 flattexnames[idx] = OGL_BindTexFlat(firstflat+idx);
244         }
245         texw = texh = 64;
246         texmask = 0;
247         return flattexnames[idx];
248 }
249
250 void OGL_SetFlat(int idx)
251 {
252         glBindTexture(GL_TEXTURE_2D, OGL_PrepareFlat(idx));
253 }
254
255 // Return GL_RGB or GL_RGBA.
256 static int DrawRealPatch(byte *rgbflat, byte *rgbaflat, byte *palette, int texwidth,
257                                                  int texheight, patch_t *patch, boolean maskZero)
258 {
259         int count;
260         int col;
261         column_t *column;
262         byte *desttop1, *desttop2;
263         byte *dest1=NULL, *dest2=NULL;
264         byte *source;
265         int w, i;
266
267 /*      y -= SHORT(patch->topoffset);
268         x -= SHORT(patch->leftoffset);
269         if(x < 0 || x+SHORT(patch->width) > SCREENWIDTH || y < 0
270                 || y+SHORT(patch->height) > SCREENHEIGHT)
271         {
272                 I_Error("Bad V_DrawPatch");
273         }*/
274         col = 0;
275         desttop1 = rgbflat;// + y*SCREENWIDTH+x;
276         desttop2 = rgbaflat;
277         w = SHORT(patch->width);
278         for(; col < w; /*x++,*/ col++, desttop1+=3, desttop2+=4)
279         {
280                 column = (column_t *)((byte *)patch+LONG(patch->columnofs[col]));
281                 // Step through the posts in a column
282                 while(column->topdelta != 0xff)
283                 {
284                         source = (byte *)column+3;
285                         if(rgbflat) dest1 = desttop1 + column->topdelta*texwidth*3;
286                         if(rgbaflat) dest2 = desttop2 + column->topdelta*texwidth*4;
287                         count = column->length;
288                         while(count--)
289                         {
290                                 int palidx = *source++;
291                                 if(rgbflat)     
292                                 {
293                                         if(!maskZero || palidx) PalIdxToRGB(palette, palidx, dest1);
294                                         dest1 += texwidth*3;
295                                 }
296                                 if(rgbaflat)
297                                 {
298                                         if(!maskZero || palidx)
299                                         {
300                                                 PalIdxToRGB(palette, palidx, dest2);
301                                                 *(dest2+3) = 0xff;      // This pixel is not clear.
302                                         }
303                                         dest2 += texwidth*4;
304                                 }
305                         }
306                         column = (column_t *)((byte *)column+column->length+4);
307                 }
308         }
309         // Scan through the RGBA buffer and check for sub-0xff alpha.
310         if(rgbflat && rgbaflat) // Which one is it?
311         {
312                 for(i=0; i<texwidth*texheight; i++)
313                         if(*(rgbaflat + i*4 + 3) != 0xff) return GL_RGBA;                               
314         }
315         if(rgbflat) return GL_RGB;
316         return GL_RGBA;
317         //else return GL_RGBA;  // Must be rgba.
318         // No alpha was found, RGB is enough.
319         //return GL_RGB;
320 }
321
322 // Returns the OpenGL texture name.
323 unsigned int OGL_PrepareTexture(int idx)
324 {
325         if(idx == 0)
326         {
327                 // No texture?
328                 //glBindTexture(GL_TEXTURE_2D, 0);
329                 //curtex = 0;
330                 texw = 1;
331                 texh = 1;
332                 texmask = 0;
333                 return 0;
334         }
335         idx = texturetranslation[idx];
336         if(!texnames[idx])
337         {
338                 // The texture must be given to OpenGL.
339                 int i, k, textype;
340                 texture_t *tex = textures[idx];
341                 byte *palette = W_CacheLumpNum(pallump, PU_CACHE);
342                 byte *rgbflat = _alloca(3*tex->width*tex->height);
343                 byte *colptr;
344         
345                 if(tex->patchcount > 1)
346                 {
347                         textype = GL_RGB;
348                         for(i=0; i<tex->width; i++)
349                         {
350                                 colptr = R_GetColumn(idx,i);
351                                 for(k=0; k<tex->height; k++)
352                                         PalIdxToRGB(palette, colptr[k], rgbflat+(k*tex->width+i)*3);
353                         }
354                 }
355                 else 
356                 {
357                         // This texture has only only one patch. It might be masked.
358                         byte *rgbaflat = _alloca(4*tex->width*tex->height);
359                         memset(rgbaflat, 0, 4*tex->width*tex->height);
360                         textype = DrawRealPatch(rgbflat, rgbaflat, palette,     tex->width, tex->height,
361                                 W_CacheLumpNum(tex->patches[0].patch, PU_CACHE), false);
362                         if(textype == GL_RGBA) rgbflat = rgbaflat;
363                 }
364                                                 
365                 // Generate and bind the texture.
366                 glGenTextures(1, texnames+idx);
367                 glBindTexture(GL_TEXTURE_2D, texnames[idx]);
368                 gluBuild2DMipmaps(GL_TEXTURE_2D, (textype==GL_RGB)?3:4, tex->width, 
369                         tex->height, textype, GL_UNSIGNED_BYTE, rgbflat);
370                 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
371                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmapping]);
372                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
373
374                 if(textype == GL_RGBA) texmasked[idx] = 1;      // Yes it is.
375         }
376         texw = textures[idx]->width;
377         texh = textures[idx]->height;
378         texmask = texmasked[idx];
379         return texnames[idx];
380 }
381
382 void OGL_SetTexture(int idx)
383 {
384         glBindTexture(GL_TEXTURE_2D, OGL_PrepareTexture(idx));
385 }
386
387 int LineAverageRGB(byte *imgdata, int components, int width, int line, byte *rgb,
388                                         byte *palette)
389 {
390         byte    *start = imgdata + components*width*line;
391         int             i, c, count = 0;
392         int             integerRGB[3] = {0,0,0};
393
394         for(i=0; i<width; i++)
395         {
396                 byte *pixpos = start + i*components;
397                 if(*(pixpos+3) > 0)     // Not transparent?
398                 {
399                         count++;
400                         for(c=0; c<3; c++) integerRGB[c] += pixpos[c];
401                 }
402         }
403         // All transparent? Sorry...
404         if(!count) return 0;
405
406         // We're going to make it!
407         for(c=0; c<3; c++) rgb[c] = integerRGB[c]/count;
408         return 1;       // Successful.
409 }
410
411 void ImageAverageRGB(byte *imgdata, int components, int width, int height, byte *rgb,
412                                          byte *palette)
413 {
414         int     i, c, integerRGB[3] = {0,0,0}, count = 0;
415
416         for(i=0; i<height; i++)
417         {
418                 if(LineAverageRGB(imgdata, components, width, i, rgb, palette))
419                 {
420                         count++;
421                         for(c=0; c<3; c++) integerRGB[c] += rgb[c];
422                 }
423         }
424         if(count)       // If there were pixels...
425                 for(c=0; c<3; c++) 
426                         rgb[c] = integerRGB[c]/count;
427 }
428
429 unsigned int OGL_PrepareSky(int idx, boolean zeroMask)
430 {
431         if(idx != texturetranslation[idx])
432                 I_Error("Skytex: %d, translated: %d\n", idx, texturetranslation[idx]);
433         
434         idx = texturetranslation[idx];
435         
436         if(!texnames[idx])
437         {
438                 int                     i, k;
439                 byte            *palette = W_CacheLumpNum(pallump, PU_CACHE);
440                 texture_t       *tex = textures[idx];
441                 int                     textype, numpels = 256*256;     // 'Full' size.
442                 byte            *imgdata, *colptr;
443                 // Choose the right format.
444                 if(zeroMask)
445                 {
446                         textype = GL_RGBA;
447                         imgdata = _alloca(4*numpels);
448                         memset(imgdata, 0, 4*numpels);
449                 }
450                 else
451                 {
452                         textype = GL_RGB;
453                         imgdata = _alloca(3*numpels);
454                         memset(imgdata, 0, 3*numpels);
455                 }
456                 if(tex->patchcount > 1)
457                 {
458                         for(i=0; i<tex->width; i++)
459                         {
460                                 colptr = R_GetColumn(idx, i);
461                                 for(k=0; k<tex->height; k++)
462                                 {
463                                         if(textype == GL_RGB)
464                                                 PalIdxToRGB(palette, colptr[k], imgdata+(k*256+i)*3);
465                                         else if(textype == GL_RGBA && colptr[k])
466                                         {
467                                                 byte *imgpos = imgdata+(k*256+i)*4;
468                                                 PalIdxToRGB(palette, colptr[k], imgpos);
469                                                 *(imgpos+3) = 0xff;     // Not transparent, this pixel.
470                                         }
471                                 }
472                         }
473                 }
474                 else 
475                 {
476                         // This texture has only only one patch.
477                         if(textype == GL_RGB)
478                                 DrawRealPatch(imgdata, 0, palette, 256, tex->height, 
479                                         W_CacheLumpNum(tex->patches[0].patch, PU_CACHE), false);
480                         else if(textype == GL_RGBA) // Mask out zeros.
481                                 DrawRealPatch(0, imgdata, palette, 256, tex->height,
482                                         W_CacheLumpNum(tex->patches[0].patch, PU_CACHE), true);
483                 }
484                 if(textype == GL_RGBA)  // For masked data, calculate the alpha-fill color.
485                 {
486                         byte rgbAverage[3];     
487                         ImageAverageRGB(imgdata, 4, 256, 200, rgbAverage, palette);
488                         // Fill all the transparent places.
489                         for(i=0; i<256*200; i++)
490                         {
491                                 byte *pixel = imgdata + 4*i;
492                                 if(!pixel[3]) memcpy(pixel, rgbAverage, 3);
493                         }
494                 }
495                 // Calculate the topline RGB for sky top fadeouts.
496                 memset(topLineRGB, 0, 3);
497                 LineAverageRGB(imgdata, (textype==GL_RGB)?3:4, 256, 0, topLineRGB, palette);
498
499                 // Generate and bind the texture.
500                 glGenTextures(1, texnames+idx);
501                 glBindTexture(GL_TEXTURE_2D, texnames[idx]);
502                 if(test3dfx)
503                 {
504                         glTexImage2D(GL_TEXTURE_2D, 0, (textype==GL_RGB)?3:4, 256, 256, 0, GL_RGB, 
505                                 GL_UNSIGNED_BYTE, imgdata);
506                 }
507                 else
508                         gluBuild2DMipmaps(GL_TEXTURE_2D, (textype==GL_RGB)?3:4, 256, 256, textype, 
509                                 GL_UNSIGNED_BYTE, imgdata);
510 //              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
511                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmapping]);
512                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
513
514                 // Do we have a masked texture?
515                 if(textype == GL_RGBA) 
516                         texmasked[idx] = 1;
517                 else
518                         texmasked[idx] = 0;
519         }
520         texw = textures[idx]->width;
521         texh = textures[idx]->height;
522         texmask = texmasked[idx];
523         return texnames[idx];
524 }
525
526 unsigned int OGL_PrepareSprite(int pnum)
527 {
528         if(!spritenames[pnum])
529         {
530                 // There's no name for this patch, load it in.
531                 patch_t *patch = W_CacheLumpNum(firstspritelump+pnum, PU_CACHE);
532                 int p2width = FindNextPower2(patch->width), 
533                         p2height = OGL_ValidTexHeight2(patch->width, patch->height);// FindNextPower2(patch->height);
534                 int flatsize = 4*p2width*p2height;
535                 byte *rgbaflat = _alloca(flatsize);
536                 
537                 //printf( "orig: %d x %d => %d x %d\n", patch->width, patch->height, p2width, p2height);
538
539                 memset(rgbaflat, 0, flatsize);
540                 DrawRealPatch(0, rgbaflat, W_CacheLumpNum(pallump,PU_CACHE),
541                         p2width, p2height, patch, false);
542
543                 // Generate and bind the texture.
544                 glGenTextures(1, spritenames+pnum);
545                 glBindTexture(GL_TEXTURE_2D, spritenames[pnum]);
546                 gluBuild2DMipmaps(GL_TEXTURE_2D, 4, p2width, p2height, GL_RGBA, 
547                         GL_UNSIGNED_BYTE, rgbaflat);
548                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmapping]);
549                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
550                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
551                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
552
553                 spriteheights[pnum] = patch->height;
554         }
555         return spritenames[pnum];
556 }
557  
558 void OGL_SetSprite(int pnum)
559 {
560         OGL_BindTexture(OGL_PrepareSprite(pnum));
561 }
562
563 void OGL_NewRawLump(int lump)
564 {
565         rawlumps = realloc(rawlumps, sizeof(int) * ++numrawlumps);
566         rawlumps[numrawlumps-1] = lump;
567 }
568
569 GLuint OGL_GetOtherPart(int lump)
570 {
571         return lumptexnames2[lump];
572 }
573
574 // Part is either 1 or 2. Part 0 means only the left side is loaded.
575 // No splittex is created in that case. Once a raw image is loaded
576 // as part 0 it must be deleted before the other part is loaded at the
577 // next loading.
578 void OGL_SetRawImage(int lump, int part)
579 {
580         if(part < 0 || part > 2) return;        // Check the part.
581
582         if(!lumptexnames[lump])
583         {
584                 // Load the raw texture data (320x200).
585                 // We'll create two textures (256x256 and 64x256).
586                 byte *raw = W_CacheLumpNum(lump, PU_CACHE);
587                 byte *dat1 = _alloca(3*256*256);        // Let's hope there's enough stack!
588                 byte *dat2 = _alloca(3*64*256);
589                 byte *palette = W_CacheLumpNum(pallump, PU_CACHE);
590                 int i,k;
591                 memset(dat1, 0, 3*256*256);     // Why must this be done?
592                 for(k=0; k<200; k++)
593                         for(i=0; i<256; i++)
594                         {
595                                 // We can't go over the end.
596                                 if(k*320+i > lumpinfo[lump].size-1) break;
597                                 // Part one.
598                                 PalIdxToRGB(palette, *(raw+(k*320+i)), dat1+3*(k*256+i));
599                                 if(i<64 && part) // Part two?
600                                         PalIdxToRGB(palette, *(raw+(k*320+i+256)), dat2+3*(k*64+i));
601                         }
602
603                 // Do a special fill for textures with h<200 (part 0).
604                 if(/*lumpinfo[lump].size/320 < 200 &&*/ !part)
605                 {
606                         int lines = lumpinfo[lump].size/320;
607                         // Copy the missing data from the beginning.
608                         memcpy(dat1+lines*256*3, dat1, 3*256*(256-lines));
609                 }
610                         
611                 // Generate and load the textures.
612                 glGenTextures(1, lumptexnames+lump);
613                 glBindTexture(GL_TEXTURE_2D, lumptexnames[lump]);
614                 glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, dat1);
615                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
616                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linearRaw? GL_LINEAR : GL_NEAREST);
617                 
618                 if(part)
619                 {
620                         // And the other part.
621                         glGenTextures(1, lumptexnames2+lump);
622                         glBindTexture(GL_TEXTURE_2D, lumptexnames2[lump]);
623                         glTexImage2D(GL_TEXTURE_2D, 0, 3, 64, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, dat2);
624                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
625                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linearRaw? GL_LINEAR : GL_NEAREST);
626                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
627
628                         // Add it to the list.
629                         OGL_NewRawLump(lump);
630                 }
631
632                 lumptexsizes[lump].w = 256;
633                 lumptexsizes[lump].w2 = 64;
634                 lumptexsizes[lump].h = 200;
635         }
636         // Bind the correct part.
637         if(part <= 1) glBindTexture(GL_TEXTURE_2D, lumptexnames[lump]);
638         if(part == 2) glBindTexture(GL_TEXTURE_2D, lumptexnames2[lump]);
639         // We don't track the current texture with raw images.
640         curtex = 0;
641 }
642
643 // Copies a rectangular region of the source buffer to the destination
644 // buffer. Doesn't perform clipping, so be careful.
645 static void pixBlt(byte *src, int srcWidth, byte *dest, int destWidth, int pixelSize, 
646                                    int srcRegX, int srcRegY, int destRegX, int destRegY,
647                                    int regWidth, int regHeight)
648 {
649         int     y;      // Y in the copy region.
650         for(y=0; y<regHeight; y++) // Copy line by line.
651                 memcpy(dest + pixelSize*(destRegX + (y+destRegY)*destWidth),
652                         src + pixelSize*(srcRegX + (y+srcRegY)*srcWidth),
653                         pixelSize*regWidth);
654 }
655
656 // Notices ratiolimit.
657 int OGL_ValidTexHeight2(int width, int height)
658 {
659         int p2w, p2h = FindNextPower2(height);
660         int minheight;
661
662         if(!ratioLimit) return p2h;
663
664         p2w = FindNextPower2(width);
665         // Do we have to notice that the texture will be split?
666         if(p2w > maxTexSize)
667         {
668                 int part2width = FindNextPower2(width - maxTexSize);
669                 int height1 = maxTexSize/ratioLimit,
670                         height2 = part2width/ratioLimit;
671                 minheight = height1 > height2? height1 : height2;
672         }
673         else minheight = p2w/ratioLimit;
674         // Do the test.
675         if(minheight > p2h) return minheight;
676         return p2h;
677 }
678
679 void OGL_SetPatch(int lump)     // No mipmaps are generated.
680 {
681         if(!lumptexnames[lump])
682         {
683                 // Load the patch.
684                 patch_t *patch = W_CacheLumpNum(lump, PU_CACHE);
685                 int             p2width = FindNextPower2(patch->width), 
686                                 p2height = OGL_ValidTexHeight2(patch->width, patch->height);//FindNextPower2(patch->height);
687                 int             numpels = p2width*p2height;
688                 byte    *rgbflat = _alloca(3*numpels), 
689                                 *rgbaflat = _alloca(4*numpels);
690                 int             ptype;
691                 
692                 memset(rgbaflat, 0, 4*numpels);
693                 ptype = DrawRealPatch(rgbflat, rgbaflat, W_CacheLumpNum(pallump,PU_CACHE),
694                         p2width, p2height, patch, false);
695
696                 // See if we have to split the patch into two parts.
697                 if(p2width > maxTexSize) // Nothing about the height...
698                 {
699                         // Notice: This is only vertical splitting, p2height 
700                         // applies to both parts. 
701                         // The width of the first part is maxTexSize.
702                         int part2width = FindNextPower2(patch->width - maxTexSize);
703                         byte *tempbuff = _alloca(4*maxTexSize*p2height);
704                         if(part2width > maxTexSize)
705                                 I_Error("OGL_SetPatch: Too wide texture (really: %d, pow2: %d).\n", patch->width, p2width);
706                         // We'll use a temporary buffer for doing to splitting.
707                         // First, part one.
708                         pixBlt(ptype==GL_RGB? rgbflat : rgbaflat, p2width, tempbuff,
709                                 maxTexSize, ptype==GL_RGB? 3 : 4,
710                                 0, 0, 0, 0, maxTexSize, p2height);
711                         // Generate a texture.
712                         glGenTextures(1, lumptexnames+lump);
713                         glBindTexture(GL_TEXTURE_2D, lumptexnames[lump]);
714                         // There won't be mipmapping versions.
715                         glTexImage2D(GL_TEXTURE_2D, 0, ptype==GL_RGB? 3 : 4, maxTexSize, p2height,
716                                 0, ptype, GL_UNSIGNED_BYTE, tempbuff);
717                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
718                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
719                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
720                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
721
722                         // Then part two.
723                         pixBlt(ptype==GL_RGB? rgbflat : rgbaflat, p2width, tempbuff,
724                                 part2width, ptype==GL_RGB? 3 : 4, 
725                                 maxTexSize, 0, 0, 0, part2width, p2height);
726                         // Generate a texture.
727                         glGenTextures(1, lumptexnames2+lump);
728                         glBindTexture(GL_TEXTURE_2D, lumptexnames2[lump]);
729                         // There won't be mipmapping versions.
730                         glTexImage2D(GL_TEXTURE_2D, 0, ptype==GL_RGB? 3 : 4, part2width, p2height,
731                                 0, ptype, GL_UNSIGNED_BYTE, tempbuff);
732                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
733                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
734                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
735                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
736
737                         OGL_BindTexture(lumptexnames[lump]);
738
739                         lumptexsizes[lump].w = maxTexSize;
740                         lumptexsizes[lump].w2 = patch->width - maxTexSize;
741                 }
742                 else // We can use the normal one-part method.
743                 {
744                         // Generate a texture.
745                         glGenTextures(1, lumptexnames+lump);
746                         glBindTexture(GL_TEXTURE_2D, lumptexnames[lump]);
747                         // There won't be mipmapping versions.
748                         glTexImage2D(GL_TEXTURE_2D, 0, (ptype==GL_RGB)?3:4, p2width, p2height,
749                                 0, ptype, GL_UNSIGNED_BYTE, (ptype==GL_RGB)?rgbflat:rgbaflat);
750                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
751                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
752
753                         lumptexsizes[lump].w = patch->width;
754                         lumptexsizes[lump].w2 = 0;
755                 }
756                 // The rest of the size information.
757                 lumptexsizes[lump].h = patch->height;
758                 lumptexsizes[lump].offx = -patch->leftoffset;
759                 lumptexsizes[lump].offy = -patch->topoffset;
760         }
761         else
762         {
763                 OGL_BindTexture(lumptexnames[lump]);
764         }
765         curtex = lumptexnames[lump];
766 }
767
768 #if 0
769 // Drawing polygons with an unset texture causes a segfault with Mesa 3.0.
770 // I guess Windows OpenGL handles this ok.
771 // I am disabling texturing when needed rather than binding an unset texture.
772 void OGL_SetNoTexture()
773 {
774
775         //glBindTexture(GL_TEXTURE_2D, 0);
776         glDisable( GL_TEXTURE_2D );
777
778         curtex = 0;
779 }
780 #endif
781
782 GLuint OGL_PrepareLightTexture()
783 {
784         if(!dltexname)
785         {
786                 // We need to generate the texture, I see.
787                 byte *image = W_CacheLumpName("DLIGHT", PU_CACHE);
788                 if(!image)
789                         I_Error("OGL_SetLightTexture: no dlight texture.\n");
790                 // The dynamic light map is a 64x64 grayscale 8-bit image.
791                 glGenTextures(1, &dltexname);
792                 glBindTexture(GL_TEXTURE_2D, dltexname);
793
794                 glTexImage2D(GL_TEXTURE_2D, 0, 1, 64, 64, 0, GL_LUMINANCE, 
795                         GL_UNSIGNED_BYTE, image);
796                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
797                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
798                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
799                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
800         }
801         // Set the info.
802         texw = texh = 64;
803         texmask = 0;
804         return dltexname;
805 }
806
807 int OGL_GetLumpTexWidth(int lump)
808 {
809         return lumptexsizes[lump].w;
810 }
811
812 int OGL_GetLumpTexHeight(int lump)
813 {
814         return lumptexsizes[lump].h;
815 }
816
817 // Updates the textures, flats and sprites.
818 void OGL_UpdateTexParams(int mipmode)
819 {
820         int     i;
821         
822         // Textures.
823         for(i=0; i<numtextures; i++)
824                 if(texnames[i]) // Is the texture loaded?
825                 {
826                         glBindTexture(GL_TEXTURE_2D, texnames[i]);
827                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmode]);
828                 }
829         // Flats.
830         for(i=0; i<numflats; i++)
831                 if(flattexnames[i]) // Is the texture loaded?
832                 {
833                         glBindTexture(GL_TEXTURE_2D, flattexnames[i]);
834                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmode]);
835                 }
836         // Sprites.
837         for(i=0; i<numspritelumps; i++)
838                 if(spritenames[i])
839                 {
840                         glBindTexture(GL_TEXTURE_2D, spritenames[i]);
841                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmode]);
842                 }
843 }
844
845 // Updates the raw screen smoothing (linear magnification).
846 // This is the main reason for having the rawlumps table.
847 void OGL_UpdateRawScreenParams(int smoothing)
848 {
849         int             i;
850         int             glmode = (smoothing)? GL_LINEAR : GL_NEAREST;
851
852         for(i=0; i<numrawlumps; i++)
853         {
854                 // First part 1.
855                 glBindTexture(GL_TEXTURE_2D, lumptexnames[rawlumps[i]]);
856                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glmode);
857                 // Then part 2.
858                 glBindTexture(GL_TEXTURE_2D, lumptexnames2[rawlumps[i]]);
859                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glmode);
860         }
861 }