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