osezer patch 007
[theoddone33/hhexen.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 "h2def.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 = (byte*)malloc(3*lumpinfo[lump].size);
203         
204         //printf( "OGL_SetFlat: Loading flat %d.\n",idx);
205         // Convert the data to RGB.
206         for(i=0, p=0; i<lumpinfo[lump].size; i++)
207                 PalIdxToRGB(palette, flatptr[i], rgbflat+i*3);
208
209         // Generate and bind the texture.
210         glGenTextures(1, &name);//flattexnames+idx);
211         glBindTexture(GL_TEXTURE_2D, name);//flattexnames[idx]);
212         
213         // Set the texture properties.
214         if(test3dfx)
215         {
216                 glTexImage2D(GL_TEXTURE_2D, 0, 3, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, rgbflat);
217         }
218         else
219                 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 64, 64, GL_RGB, GL_UNSIGNED_BYTE, rgbflat);
220         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmapping]);
221         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
222
223         // Change the tag.
224         Z_ChangeTag(flatptr, PU_CACHE);
225         free (rgbflat);
226         return name;
227 }
228
229 // Returns the OpenGL name of the texture.
230 unsigned int OGL_PrepareFlat(int idx)
231 {
232         idx = flattranslation[idx];
233         if(!flattexnames[idx])
234         {
235                 // The flat isn't yet bound with OpenGL.
236                 flattexnames[idx] = OGL_BindTexFlat(firstflat+idx);
237         }
238         texw = texh = 64;
239         texmask = 0;
240         return flattexnames[idx];
241 }
242
243 void OGL_SetFlat(int idx)
244 {
245         glBindTexture(GL_TEXTURE_2D, OGL_PrepareFlat(idx));
246 }
247
248 // Return GL_RGB or GL_RGBA.
249 static int DrawRealPatch(byte *rgbflat, byte *rgbaflat, byte *palette, int texwidth,
250                                                  int texheight, patch_t *patch, boolean maskZero)
251 {
252         int count;
253         int col;
254         column_t *column;
255         byte *desttop1, *desttop2;
256         byte *dest1=NULL, *dest2=NULL;
257         byte *source;
258         int w, i;
259
260 /*      y -= SHORT(patch->topoffset);
261         x -= SHORT(patch->leftoffset);
262         if(x < 0 || x+SHORT(patch->width) > SCREENWIDTH || y < 0
263                 || y+SHORT(patch->height) > SCREENHEIGHT)
264         {
265                 I_Error("Bad V_DrawPatch");
266         }*/
267         col = 0;
268         desttop1 = rgbflat;// + y*SCREENWIDTH+x;
269         desttop2 = rgbaflat;
270         w = SHORT(patch->width);
271         for(; col < w; /*x++,*/ col++, desttop1+=3, desttop2+=4)
272         {
273                 column = (column_t *)((byte *)patch+LONG(patch->columnofs[col]));
274                 // Step through the posts in a column
275                 while(column->topdelta != 0xff)
276                 {
277                         source = (byte *)column+3;
278                         if(rgbflat) dest1 = desttop1 + column->topdelta*texwidth*3;
279                         if(rgbaflat) dest2 = desttop2 + column->topdelta*texwidth*4;
280                         count = column->length;
281                         while(count--)
282                         {
283                                 int palidx = *source++;
284                                 if(rgbflat)     
285                                 {
286                                         if(!maskZero || palidx) PalIdxToRGB(palette, palidx, dest1);
287                                         dest1 += texwidth*3;
288                                 }
289                                 if(rgbaflat)
290                                 {
291                                         if(!maskZero || palidx)
292                                         {
293                                                 PalIdxToRGB(palette, palidx, dest2);
294                                                 *(dest2+3) = 0xff;      // This pixel is not clear.
295                                         }
296                                         dest2 += texwidth*4;
297                                 }
298                         }
299                         column = (column_t *)((byte *)column+column->length+4);
300                 }
301         }
302         // Scan through the RGBA buffer and check for sub-0xff alpha.
303         if(rgbflat && rgbaflat) // Which one is it?
304         {
305                 for(i=0; i<texwidth*texheight; i++)
306                         if(*(rgbaflat + i*4 + 3) != 0xff) return GL_RGBA;                               
307         }
308         if(rgbflat) return GL_RGB;
309         return GL_RGBA;
310         //else return GL_RGBA;  // Must be rgba.
311         // No alpha was found, RGB is enough.
312         //return GL_RGB;
313 }
314
315 // Returns the OpenGL texture name.
316 unsigned int OGL_PrepareTexture(int idx)
317 {
318         if(idx == 0)
319         {
320                 // No texture?
321                 //glBindTexture(GL_TEXTURE_2D, 0);
322                 //curtex = 0;
323                 texw = 1;
324                 texh = 1;
325                 texmask = 0;
326                 return 0;
327         }
328         idx = texturetranslation[idx];
329         if(!texnames[idx])
330         {
331                 // The texture must be given to OpenGL.
332                 int i, k, textype;
333                 texture_t *tex = textures[idx];
334                 byte *palette = W_CacheLumpNum(pallump, PU_CACHE);
335                 byte *rgbflat = (byte *)malloc(3*tex->width*tex->height);
336                 byte *colptr;
337         
338                 if(tex->patchcount > 1)
339                 {
340                         textype = GL_RGB;
341                         for(i=0; i<tex->width; i++)
342                         {
343                                 colptr = R_GetColumn(idx,i);
344                                 for(k=0; k<tex->height; k++)
345                                         PalIdxToRGB(palette, colptr[k], rgbflat+(k*tex->width+i)*3);
346                         }
347                 }
348                 else 
349                 {
350                         // This texture has only only one patch. It might be masked.
351                         byte *rgbaflat = (byte*)malloc(4*tex->width*tex->height);
352                         memset(rgbaflat, 0, 4*tex->width*tex->height);
353                         textype = DrawRealPatch(rgbflat, rgbaflat, palette,     tex->width, tex->height,
354                                 W_CacheLumpNum(tex->patches[0].patch, PU_CACHE), false);
355                         if(textype == GL_RGBA) { free(rgbflat); rgbflat = rgbaflat; }
356                         else { free (rgbaflat); }
357                 }
358                                                 
359                 // Generate and bind the texture.
360                 glGenTextures(1, texnames+idx);
361                 glBindTexture(GL_TEXTURE_2D, texnames[idx]);
362                 gluBuild2DMipmaps(GL_TEXTURE_2D, (textype==GL_RGB)?3:4, tex->width, 
363                         tex->height, textype, GL_UNSIGNED_BYTE, rgbflat);
364                 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
365                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmapping]);
366                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
367
368                 if(textype == GL_RGBA) texmasked[idx] = 1;      // Yes it is.
369
370                 free (rgbflat);
371         }
372         texw = textures[idx]->width;
373         texh = textures[idx]->height;
374         texmask = texmasked[idx];
375         return texnames[idx];
376 }
377
378 void OGL_SetTexture(int idx)
379 {
380         glBindTexture(GL_TEXTURE_2D, OGL_PrepareTexture(idx));
381 }
382
383 int LineAverageRGB(byte *imgdata, int components, int width, int line, byte *rgb,
384                                         byte *palette)
385 {
386         byte    *start = imgdata + components*width*line;
387         int             i, c, count = 0;
388         int             integerRGB[3] = {0,0,0};
389
390         for(i=0; i<width; i++)
391         {
392                 byte *pixpos = start + i*components;
393                 if(*(pixpos+3) > 0)     // Not transparent?
394                 {
395                         count++;
396                         for(c=0; c<3; c++) integerRGB[c] += pixpos[c];
397                 }
398         }
399         // All transparent? Sorry...
400         if(!count) return 0;
401
402         // We're going to make it!
403         for(c=0; c<3; c++) rgb[c] = integerRGB[c]/count;
404         return 1;       // Successful.
405 }
406
407 void ImageAverageRGB(byte *imgdata, int components, int width, int height, byte *rgb,
408                                          byte *palette)
409 {
410         int     i, c, integerRGB[3] = {0,0,0}, count = 0;
411
412         for(i=0; i<height; i++)
413         {
414                 if(LineAverageRGB(imgdata, components, width, i, rgb, palette))
415                 {
416                         count++;
417                         for(c=0; c<3; c++) integerRGB[c] += rgb[c];
418                 }
419         }
420         if(count)       // If there were pixels...
421                 for(c=0; c<3; c++) 
422                         rgb[c] = integerRGB[c]/count;
423 }
424
425 unsigned int OGL_PrepareSky(int idx, boolean zeroMask)
426 {
427         if(idx != texturetranslation[idx])
428                 I_Error("Skytex: %d, translated: %d\n", idx, texturetranslation[idx]);
429         
430         idx = texturetranslation[idx];
431         
432         if(!texnames[idx])
433         {
434                 int                     i, k;
435                 byte            *palette = W_CacheLumpNum(pallump, PU_CACHE);
436                 texture_t       *tex = textures[idx];
437                 int                     textype, numpels = 256*256;     // 'Full' size.
438                 byte            *imgdata, *colptr;
439                 // Choose the right format.
440                 if(zeroMask)
441                 {
442                         textype = GL_RGBA;
443                         imgdata = (byte *)malloc(4*numpels);
444                         memset(imgdata, 0, 4*numpels);
445                 }
446                 else
447                 {
448                         textype = GL_RGB;
449                         imgdata = (byte *)malloc(3*numpels);
450                         memset(imgdata, 0, 3*numpels);
451                 }
452                 if(tex->patchcount > 1)
453                 {
454                         for(i=0; i<tex->width; i++)
455                         {
456                                 colptr = R_GetColumn(idx, i);
457                                 for(k=0; k<tex->height; k++)
458                                 {
459                                         if(textype == GL_RGB)
460                                                 PalIdxToRGB(palette, colptr[k], imgdata+(k*256+i)*3);
461                                         else if(textype == GL_RGBA && colptr[k])
462                                         {
463                                                 byte *imgpos = imgdata+(k*256+i)*4;
464                                                 PalIdxToRGB(palette, colptr[k], imgpos);
465                                                 *(imgpos+3) = 0xff;     // Not transparent, this pixel.
466                                         }
467                                 }
468                         }
469                 }
470                 else 
471                 {
472                         // This texture has only only one patch.
473                         if(textype == GL_RGB)
474                                 DrawRealPatch(imgdata, 0, palette, 256, tex->height, 
475                                         W_CacheLumpNum(tex->patches[0].patch, PU_CACHE), false);
476                         else if(textype == GL_RGBA) // Mask out zeros.
477                                 DrawRealPatch(0, imgdata, palette, 256, tex->height,
478                                         W_CacheLumpNum(tex->patches[0].patch, PU_CACHE), true);
479                 }
480                 if(textype == GL_RGBA)  // For masked data, calculate the alpha-fill color.
481                 {
482                         byte rgbAverage[3];     
483                         ImageAverageRGB(imgdata, 4, 256, 200, rgbAverage, palette);
484                         // Fill all the transparent places.
485                         for(i=0; i<256*200; i++)
486                         {
487                                 byte *pixel = imgdata + 4*i;
488                                 if(!pixel[3]) memcpy(pixel, rgbAverage, 3);
489                         }
490                 }
491                 // Calculate the topline RGB for sky top fadeouts.
492                 memset(topLineRGB, 0, 3);
493                 LineAverageRGB(imgdata, (textype==GL_RGB)?3:4, 256, 0, topLineRGB, palette);
494
495                 // Generate and bind the texture.
496                 glGenTextures(1, texnames+idx);
497                 glBindTexture(GL_TEXTURE_2D, texnames[idx]);
498                 if(test3dfx)
499                 {
500                         glTexImage2D(GL_TEXTURE_2D, 0, (textype==GL_RGB)?3:4, 256, 256, 0, GL_RGB, 
501                                 GL_UNSIGNED_BYTE, imgdata);
502                 }
503                 else
504                         gluBuild2DMipmaps(GL_TEXTURE_2D, (textype==GL_RGB)?3:4, 256, 256, textype, 
505                                 GL_UNSIGNED_BYTE, imgdata);
506 //              glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
507                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmapping]);
508                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
509
510                 // Do we have a masked texture?
511                 if(textype == GL_RGBA) 
512                         texmasked[idx] = 1;
513                 else
514                         texmasked[idx] = 0;
515
516                 free (imgdata);
517         }
518         texw = textures[idx]->width;
519         texh = textures[idx]->height;
520         texmask = texmasked[idx];
521         return texnames[idx];
522 }
523
524 unsigned int OGL_PrepareSprite(int pnum)
525 {
526         if(!spritenames[pnum])
527         {
528                 // There's no name for this patch, load it in.
529                 patch_t *patch = W_CacheLumpNum(firstspritelump+pnum, PU_CACHE);
530                 int p2width = FindNextPower2(patch->width), 
531                         p2height = OGL_ValidTexHeight2(patch->width, patch->height);// FindNextPower2(patch->height);
532                 int flatsize = 4*p2width*p2height;
533                 byte *rgbaflat = (byte *)malloc(flatsize);
534                 
535                 //printf( "orig: %d x %d => %d x %d\n", patch->width, patch->height, p2width, p2height);
536
537                 memset(rgbaflat, 0, flatsize);
538                 DrawRealPatch(0, rgbaflat, W_CacheLumpNum(pallump,PU_CACHE),
539                         p2width, p2height, patch, false);
540
541                 // Generate and bind the texture.
542                 glGenTextures(1, spritenames+pnum);
543                 glBindTexture(GL_TEXTURE_2D, spritenames[pnum]);
544                 gluBuild2DMipmaps(GL_TEXTURE_2D, 4, p2width, p2height, GL_RGBA, 
545                         GL_UNSIGNED_BYTE, rgbaflat);
546                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmapping]);
547                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
548                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
549                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
550
551                 spriteheights[pnum] = patch->height;
552                 free (rgbaflat);
553         }
554         return spritenames[pnum];
555 }
556  
557 void OGL_SetSprite(int pnum)
558 {
559         OGL_BindTexture(OGL_PrepareSprite(pnum));
560 }
561
562 void OGL_NewRawLump(int lump)
563 {
564         rawlumps = realloc(rawlumps, sizeof(int) * ++numrawlumps);
565         rawlumps[numrawlumps-1] = lump;
566 }
567
568 GLuint OGL_GetOtherPart(int lump)
569 {
570         return lumptexnames2[lump];
571 }
572
573 // Part is either 1 or 2. Part 0 means only the left side is loaded.
574 // No splittex is created in that case. Once a raw image is loaded
575 // as part 0 it must be deleted before the other part is loaded at the
576 // next loading.
577 void OGL_SetRawImage(int lump, int part)
578 {
579         if(part < 0 || part > 2) return;        // Check the part.
580
581         if(!lumptexnames[lump])
582         {
583                 // Load the raw texture data (320x200).
584                 // We'll create two textures (256x256 and 64x256).
585                 byte *raw = W_CacheLumpNum(lump, PU_CACHE);
586                 byte *dat1 = (byte*)malloc(3*256*256);
587                 byte *dat2 = (byte*)malloc(3*64*256);
588                 byte *palette = W_CacheLumpNum(pallump, PU_CACHE);
589                 int i,k;
590                 memset(dat1, 0, 3*256*256);     // Why must this be done?
591                 for(k=0; k<200; k++)
592                         for(i=0; i<256; i++)
593                         {
594                                 // We can't go over the end.
595                                 if(k*320+i > lumpinfo[lump].size-1) break;
596                                 // Part one.
597                                 PalIdxToRGB(palette, *(raw+(k*320+i)), dat1+3*(k*256+i));
598                                 if(i<64 && part) // Part two?
599                                         PalIdxToRGB(palette, *(raw+(k*320+i+256)), dat2+3*(k*64+i));
600                         }
601
602                 // Do a special fill for textures with h<200 (part 0).
603                 if(/*lumpinfo[lump].size/320 < 200 &&*/ !part)
604                 {
605                         int lines = lumpinfo[lump].size/320;
606                         // Copy the missing data from the beginning.
607                         memcpy(dat1+lines*256*3, dat1, 3*256*(256-lines));
608                 }
609                         
610                 // Generate and load the textures.
611                 glGenTextures(1, lumptexnames+lump);
612                 glBindTexture(GL_TEXTURE_2D, lumptexnames[lump]);
613                 glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, dat1);
614                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
615                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linearRaw? GL_LINEAR : GL_NEAREST);
616                 
617                 if(part)
618                 {
619                         // And the other part.
620                         glGenTextures(1, lumptexnames2+lump);
621                         glBindTexture(GL_TEXTURE_2D, lumptexnames2[lump]);
622                         glTexImage2D(GL_TEXTURE_2D, 0, 3, 64, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, dat2);
623                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
624                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linearRaw? GL_LINEAR : GL_NEAREST);
625                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
626
627                         // Add it to the list.
628                         OGL_NewRawLump(lump);
629                 }
630
631                 lumptexsizes[lump].w = 256;
632                 lumptexsizes[lump].w2 = 64;
633                 lumptexsizes[lump].h = 200;
634                 free (dat1);
635                 free (dat2);
636         }
637         // Bind the correct part.
638         if(part <= 1) glBindTexture(GL_TEXTURE_2D, lumptexnames[lump]);
639         if(part == 2) glBindTexture(GL_TEXTURE_2D, lumptexnames2[lump]);
640         // We don't track the current texture with raw images.
641         curtex = 0;
642 }
643
644 // Copies a rectangular region of the source buffer to the destination
645 // buffer. Doesn't perform clipping, so be careful.
646 static void pixBlt(byte *src, int srcWidth, byte *dest, int destWidth, int pixelSize, 
647                                    int srcRegX, int srcRegY, int destRegX, int destRegY,
648                                    int regWidth, int regHeight)
649 {
650         int     y;      // Y in the copy region.
651         for(y=0; y<regHeight; y++) // Copy line by line.
652                 memcpy(dest + pixelSize*(destRegX + (y+destRegY)*destWidth),
653                         src + pixelSize*(srcRegX + (y+srcRegY)*srcWidth),
654                         pixelSize*regWidth);
655 }
656
657 // Notices ratiolimit.
658 int OGL_ValidTexHeight2(int width, int height)
659 {
660         int p2w, p2h = FindNextPower2(height);
661         int minheight;
662
663         if(!ratioLimit) return p2h;
664
665         p2w = FindNextPower2(width);
666         // Do we have to notice that the texture will be split?
667         if(p2w > maxTexSize)
668         {
669                 int part2width = FindNextPower2(width - maxTexSize);
670                 int height1 = maxTexSize/ratioLimit,
671                         height2 = part2width/ratioLimit;
672                 minheight = height1 > height2? height1 : height2;
673         }
674         else minheight = p2w/ratioLimit;
675         // Do the test.
676         if(minheight > p2h) return minheight;
677         return p2h;
678 }
679
680 void OGL_SetPatch(int lump)     // No mipmaps are generated.
681 {
682         if(!lumptexnames[lump])
683         {
684                 // Load the patch.
685                 patch_t *patch = W_CacheLumpNum(lump, PU_CACHE);
686                 int             p2width = FindNextPower2(patch->width), 
687                                 p2height = OGL_ValidTexHeight2(patch->width, patch->height);//FindNextPower2(patch->height);
688                 int             numpels = p2width*p2height;
689                 byte    *rgbflat = (byte *)malloc(3*numpels), 
690                                 *rgbaflat = (byte*)malloc(4*numpels);
691                 int             ptype;
692                 
693                 memset(rgbaflat, 0, 4*numpels);
694                 ptype = DrawRealPatch(rgbflat, rgbaflat, W_CacheLumpNum(pallump,PU_CACHE),
695                         p2width, p2height, patch, false);
696
697                 // See if we have to split the patch into two parts.
698                 if(p2width > maxTexSize) // Nothing about the height...
699                 {
700                         // Notice: This is only vertical splitting, p2height 
701                         // applies to both parts. 
702                         // The width of the first part is maxTexSize.
703                         int part2width = FindNextPower2(patch->width - maxTexSize);
704                         byte *tempbuff = (byte*)malloc(4*maxTexSize*p2height);
705                         if(part2width > maxTexSize)
706                                 I_Error("OGL_SetPatch: Too wide texture (really: %d, pow2: %d).\n", patch->width, p2width);
707                         // We'll use a temporary buffer for doing to splitting.
708                         // First, part one.
709                         pixBlt(ptype==GL_RGB? rgbflat : rgbaflat, p2width, tempbuff,
710                                 maxTexSize, ptype==GL_RGB? 3 : 4,
711                                 0, 0, 0, 0, maxTexSize, p2height);
712                         // Generate a texture.
713                         glGenTextures(1, lumptexnames+lump);
714                         glBindTexture(GL_TEXTURE_2D, lumptexnames[lump]);
715                         // There won't be mipmapping versions.
716                         glTexImage2D(GL_TEXTURE_2D, 0, ptype==GL_RGB? 3 : 4, maxTexSize, p2height,
717                                 0, ptype, GL_UNSIGNED_BYTE, tempbuff);
718                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
719                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
720                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
721                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
722
723                         // Then part two.
724                         pixBlt(ptype==GL_RGB? rgbflat : rgbaflat, p2width, tempbuff,
725                                 part2width, ptype==GL_RGB? 3 : 4, 
726                                 maxTexSize, 0, 0, 0, part2width, p2height);
727                         // Generate a texture.
728                         glGenTextures(1, lumptexnames2+lump);
729                         glBindTexture(GL_TEXTURE_2D, lumptexnames2[lump]);
730                         // There won't be mipmapping versions.
731                         glTexImage2D(GL_TEXTURE_2D, 0, ptype==GL_RGB? 3 : 4, part2width, p2height,
732                                 0, ptype, GL_UNSIGNED_BYTE, tempbuff);
733                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
734                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
735                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
736                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
737
738                         OGL_BindTexture(lumptexnames[lump]);
739
740                         lumptexsizes[lump].w = maxTexSize;
741                         lumptexsizes[lump].w2 = patch->width - maxTexSize;
742                         free (tempbuff);
743                 }
744                 else // We can use the normal one-part method.
745                 {
746                         // Generate a texture.
747                         glGenTextures(1, lumptexnames+lump);
748                         glBindTexture(GL_TEXTURE_2D, lumptexnames[lump]);
749                         // There won't be mipmapping versions.
750                         glTexImage2D(GL_TEXTURE_2D, 0, (ptype==GL_RGB)?3:4, p2width, p2height,
751                                 0, ptype, GL_UNSIGNED_BYTE, (ptype==GL_RGB)?rgbflat:rgbaflat);
752                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
753                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
754
755                         lumptexsizes[lump].w = patch->width;
756                         lumptexsizes[lump].w2 = 0;
757                 }
758                 // The rest of the size information.
759                 lumptexsizes[lump].h = patch->height;
760                 lumptexsizes[lump].offx = -patch->leftoffset;
761                 lumptexsizes[lump].offy = -patch->topoffset;
762                 free (rgbflat);
763                 free (rgbaflat);
764         }
765         else
766         {
767                 OGL_BindTexture(lumptexnames[lump]);
768         }
769         curtex = lumptexnames[lump];
770 }
771
772 #if 0
773 // Drawing polygons with an unset texture causes a segfault with Mesa 3.0.
774 // I guess Windows OpenGL handles this ok.
775 // I am disabling texturing when needed rather than binding an unset texture.
776 void OGL_SetNoTexture()
777 {
778
779         //glBindTexture(GL_TEXTURE_2D, 0);
780         glDisable( GL_TEXTURE_2D );
781
782         curtex = 0;
783 }
784 #endif
785
786 GLuint OGL_PrepareLightTexture()
787 {
788         if(!dltexname)
789         {
790                 // We need to generate the texture, I see.
791                 byte *image = W_CacheLumpName("DLIGHT", PU_CACHE);
792                 if(!image)
793                         I_Error("OGL_SetLightTexture: no dlight texture.\n");
794                 // The dynamic light map is a 64x64 grayscale 8-bit image.
795                 glGenTextures(1, &dltexname);
796                 glBindTexture(GL_TEXTURE_2D, dltexname);
797
798                 glTexImage2D(GL_TEXTURE_2D, 0, 1, 64, 64, 0, GL_LUMINANCE, 
799                         GL_UNSIGNED_BYTE, image);
800                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
801                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
802                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
803                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
804         }
805         // Set the info.
806         texw = texh = 64;
807         texmask = 0;
808         return dltexname;
809 }
810
811 int OGL_GetLumpTexWidth(int lump)
812 {
813         return lumptexsizes[lump].w;
814 }
815
816 int OGL_GetLumpTexHeight(int lump)
817 {
818         return lumptexsizes[lump].h;
819 }
820
821 // Updates the textures, flats and sprites.
822 void OGL_UpdateTexParams(int mipmode)
823 {
824         int     i;
825         
826         // Textures.
827         for(i=0; i<numtextures; i++)
828                 if(texnames[i]) // Is the texture loaded?
829                 {
830                         glBindTexture(GL_TEXTURE_2D, texnames[i]);
831                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmode]);
832                 }
833         // Flats.
834         for(i=0; i<numflats; i++)
835                 if(flattexnames[i]) // Is the texture loaded?
836                 {
837                         glBindTexture(GL_TEXTURE_2D, flattexnames[i]);
838                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmode]);
839                 }
840         // Sprites.
841         for(i=0; i<numspritelumps; i++)
842                 if(spritenames[i])
843                 {
844                         glBindTexture(GL_TEXTURE_2D, spritenames[i]);
845                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glmode[mipmode]);
846                 }
847 }
848
849 // Updates the raw screen smoothing (linear magnification).
850 // This is the main reason for having the rawlumps table.
851 void OGL_UpdateRawScreenParams(int smoothing)
852 {
853         int             i;
854         int             glmode = (smoothing)? GL_LINEAR : GL_NEAREST;
855
856         for(i=0; i<numrawlumps; i++)
857         {
858                 // First part 1.
859                 glBindTexture(GL_TEXTURE_2D, lumptexnames[rawlumps[i]]);
860                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glmode);
861                 // Then part 2.
862                 glBindTexture(GL_TEXTURE_2D, lumptexnames2[rawlumps[i]]);
863                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glmode);
864         }
865 }
866