3 cvar_t gl_max_size = {"gl_max_size", "1024"};
4 cvar_t gl_picmip = {"gl_picmip", "0"};
5 cvar_t gl_lerpimages = {"gl_lerpimages", "1"};
7 int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; //NEAREST;
8 int gl_filter_max = GL_LINEAR;
19 byte *texels[MAXMIPS];
20 unsigned short texelsize[MAXMIPS][2];
23 // LordHavoc: CRC to identify cache mismatchs
28 char lerped; // whether this texture was uploaded with or without interpolation
31 #define MAX_GLTEXTURES 4096
32 gltexture_t gltextures[MAX_GLTEXTURES];
38 int minimize, maximize;
42 {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
43 {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
44 {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
45 {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
46 {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
47 {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
55 void Draw_TextureMode_f (void)
62 for (i=0 ; i< 6 ; i++)
63 if (gl_filter_min == modes[i].minimize)
65 Con_Printf ("%s\n", modes[i].name);
68 Con_Printf ("current filter is unknown???\n");
72 for (i=0 ; i< 6 ; i++)
74 if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
79 Con_Printf ("bad filter name\n");
83 gl_filter_min = modes[i].minimize;
84 gl_filter_max = modes[i].maximize;
86 // change all the existing mipmap texture objects
87 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
91 glBindTexture(GL_TEXTURE_2D, glt->texnum);
92 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
93 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
98 extern int buildnumber;
100 char engineversion[40];
102 void GL_UploadTexture (gltexture_t *glt);
103 void gl_textures_start()
107 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
108 GL_UploadTexture(glt);
111 void gl_textures_shutdown()
115 void GL_Textures_Init (void)
117 Cvar_RegisterVariable (&gl_max_size);
118 Cvar_RegisterVariable (&gl_picmip);
119 Cvar_RegisterVariable (&gl_lerpimages);
121 // 3dfx can only handle 256 wide textures
122 if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) || strstr((char *)gl_renderer, "Glide"))
123 Cvar_Set ("gl_max_size", "256");
125 Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
127 R_RegisterModule("GL_Textures", gl_textures_start, gl_textures_shutdown);
135 int GL_FindTexture (char *identifier)
140 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
142 if (!strcmp (identifier, glt->identifier))
143 return gltextures[i].texnum;
149 extern byte qgamma[];
151 // LordHavoc: gamma correction and improved resampling
152 void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
154 int j, xi, oldx = 0, f, fstep, l1, l2, endx;
155 fstep = (int) (inwidth*65536.0f/outwidth);
157 for (j = 0,f = 0;j < outwidth;j++, f += fstep)
162 in += (xi - oldx) * 4;
169 *out++ = qgamma[(byte) ((in[0] * l1 + in[4] * l2) >> 16)];
170 *out++ = qgamma[(byte) ((in[1] * l1 + in[5] * l2) >> 16)];
171 *out++ = qgamma[(byte) ((in[2] * l1 + in[6] * l2) >> 16)];
172 *out++ = (byte) ((in[3] * l1 + in[7] * l2) >> 16) ;
174 else // last pixel of the line has no pixel to lerp to
176 *out++ = qgamma[in[0]];
177 *out++ = qgamma[in[1]];
178 *out++ = qgamma[in[2]];
189 void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
191 // LordHavoc: gamma correction and greatly improved resampling
192 if (gl_lerpimages.value)
194 int i, j, yi, oldy, f, fstep, l1, l2, endy = (inheight-1);
195 byte *inrow, *out, *row1, *row2;
197 fstep = (int) (inheight*65536.0f/outheight);
199 row1 = malloc(outwidth*4);
200 row2 = malloc(outwidth*4);
203 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
204 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
205 for (i = 0, f = 0;i < outheight;i++,f += fstep)
210 inrow = (byte *)indata + inwidth*4*yi;
212 memcpy(row1, row2, outwidth*4);
214 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
216 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
218 memcpy(row2, row1, outwidth*4);
225 for (j = 0;j < outwidth;j++)
227 *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
228 *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
229 *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
230 *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
235 else // last line has no pixels to lerp to
237 for (j = 0;j < outwidth;j++)
253 unsigned frac, fracstep;
254 byte *inrow, *out, *inpix;
257 fracstep = inwidth*0x10000/outwidth;
258 for (i=0 ; i<outheight ; i++)
260 inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
261 frac = fracstep >> 1;
262 for (j=0 ; j<outwidth ; j+=4)
264 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
265 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
266 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
267 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
275 GL_Resample8BitTexture -- JACK
279 void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
282 unsigned char *inrow;
283 unsigned frac, fracstep;
285 fracstep = inwidth*0x10000/outwidth;
286 for (i=0 ; i<outheight ; i++, out += outwidth)
288 inrow = in + inwidth*(i*inheight/outheight);
289 frac = fracstep >> 1;
290 for (j=0 ; j<outwidth ; j+=4)
292 out[j ] = inrow[frac>>16];frac += fracstep;
293 out[j+1] = inrow[frac>>16];frac += fracstep;
294 out[j+2] = inrow[frac>>16];frac += fracstep;
295 out[j+3] = inrow[frac>>16];frac += fracstep;
306 Operates in place, quartering the size of the texture
310 void GL_MipMap (byte *in, int width, int height)
318 for (i=0 ; i<height ; i++, in+=width)
320 for (j=0 ; j<width ; j+=8, out+=4, in+=8)
322 out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
323 out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
324 out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
325 out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
335 Mipping for 8 bit textures
339 void GL_MipMap8Bit (byte *in, int width, int height)
342 unsigned short r,g,b;
343 byte *out, *at1, *at2, *at3, *at4;
347 for (i=0 ; i<height ; i++, in+=width)
349 for (j=0 ; j<width ; j+=2, out+=1, in+=2)
351 at1 = (byte *) (d_8to24table + in[0]);
352 at2 = (byte *) (d_8to24table + in[1]);
353 at3 = (byte *) (d_8to24table + in[width+0]);
354 at4 = (byte *) (d_8to24table + in[width+1]);
356 r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
357 g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
358 b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
360 out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
372 void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha)
374 int samples, scaled_width, scaled_height, i;
375 byte *in, *out, *scaled;
377 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
379 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
382 scaled_width >>= (int)gl_picmip.value;
383 scaled_height >>= (int)gl_picmip.value;
385 if (scaled_width > gl_max_size.value)
386 scaled_width = gl_max_size.value;
387 if (scaled_height > gl_max_size.value)
388 scaled_height = gl_max_size.value;
394 for (i = 3;i < width*height*4;i += 4)
402 samples = alpha ? gl_alpha_format : gl_solid_format;
404 texels += scaled_width * scaled_height;
406 scaled = malloc(scaled_width*scaled_height*4);
407 if (scaled_width == width && scaled_height == height)
409 // LordHavoc: gamma correct while copying
411 out = (byte *)scaled;
412 for (i = 0;i < width*height;i++)
414 *out++ = qgamma[*in++];
415 *out++ = qgamma[*in++];
416 *out++ = qgamma[*in++];
421 GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
423 glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
429 while (scaled_width > 1 || scaled_height > 1)
431 GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
434 if (scaled_width < 1)
436 if (scaled_height < 1)
439 glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
445 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
446 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
450 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
451 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
456 void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap)
458 int scaled_width, scaled_height;
461 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
463 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
466 scaled_width >>= (int)gl_picmip.value;
467 scaled_height >>= (int)gl_picmip.value;
469 if (scaled_width > gl_max_size.value)
470 scaled_width = gl_max_size.value;
471 if (scaled_height > gl_max_size.value)
472 scaled_height = gl_max_size.value;
474 texels += scaled_width * scaled_height;
476 if (scaled_width == width && scaled_height == height)
480 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
483 scaled = malloc(scaled_width*scaled_height*4);
484 memcpy (scaled, data, width*height);
488 scaled = malloc(scaled_width*scaled_height*4);
489 GL_Resample8BitTexture (data, width, height, (void*) scaled, scaled_width, scaled_height);
492 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
498 while (scaled_width > 1 || scaled_height > 1)
500 GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
503 if (scaled_width < 1)
505 if (scaled_height < 1)
508 glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
516 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
517 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
521 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
522 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
528 extern qboolean VID_Is8bit();
536 void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
538 static unsigned *trans;
547 // if there are no transparent pixels, make it a 3 component
548 // texture even if it was specified as otherwise
552 for (i=0 ; i<s ; i++)
556 trans[i] = d_8to24table[p];
559 trans[i] = 0; // force to black
566 if (VID_Is8bit() && (data!=scrap_texels[0]))
568 GL_Upload8_EXT (data, width, height, mipmap);
577 // LordHavoc: dodge the copy if it will be uploaded as 8bit
578 if (VID_Is8bit() && (data!=scrap_texels[0]))
580 GL_Upload8_EXT (data, width, height, mipmap);
585 // Sys_Error ("GL_Upload8: s&3");
589 *outdata++ = d_8to24table[*indata++];
592 *outdata++ = d_8to24table[*indata++];
593 *outdata++ = d_8to24table[*indata++];
595 for (i = 0;i < s;i+=4)
597 *outdata++ = d_8to24table[*indata++];
598 *outdata++ = d_8to24table[*indata++];
599 *outdata++ = d_8to24table[*indata++];
600 *outdata++ = d_8to24table[*indata++];
604 GL_Upload32 (trans, width, height, mipmap, alpha);
609 void GL_AllocTexels(gltexture_t *glt, int width, int height, int mipmapped)
611 int i, w, h, size, done;
613 free(glt->texels[0]);
614 glt->texelsize[0][0] = width;
615 glt->texelsize[0][1] = height;
619 w = width;h = height;
622 for (i = 0;i < MAXMIPS;i++)
624 glt->texelsize[i][0] = w;
625 glt->texelsize[i][1] = h;
626 glt->texels[i] = (void *)size;
643 glt->texels[i++] = NULL;
644 glt->texels[0] = malloc(size);
645 for (i = 1;i < MAXMIPS && glt->texels[i];i++)
646 glt->texels[i] += (int) glt->texels[0];
650 glt->texels[0] = malloc(width*height*4);
651 for (i = 1;i < MAXMIPS;i++)
652 glt->texels[i] = NULL;
655 Sys_Error("GL_AllocTexels: out of memory\n");
658 // in can be the same as out
659 void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight)
661 int x, y, width2, height2, nextrow;
662 if (width > destwidth)
664 if (height > destheight)
668 height2 = height >> 1;
669 nextrow = width << 2;
670 for (y = 0;y < height2;y++)
672 for (x = 0;x < width2;x++)
674 out[0] = (byte) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
675 out[1] = (byte) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
676 out[2] = (byte) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
677 out[3] = (byte) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
681 in += nextrow; // skip a line
688 for (y = 0;y < height;y++)
690 for (x = 0;x < width2;x++)
692 out[0] = (byte) ((in[0] + in[4]) >> 1);
693 out[1] = (byte) ((in[1] + in[5]) >> 1);
694 out[2] = (byte) ((in[2] + in[6]) >> 1);
695 out[3] = (byte) ((in[3] + in[7]) >> 1);
704 if (height > destheight)
707 height2 = height >> 1;
708 nextrow = width << 2;
709 for (y = 0;y < height2;y++)
711 for (x = 0;x < width;x++)
713 out[0] = (byte) ((in[0] + in[nextrow ]) >> 1);
714 out[1] = (byte) ((in[1] + in[nextrow+1]) >> 1);
715 out[2] = (byte) ((in[2] + in[nextrow+2]) >> 1);
716 out[3] = (byte) ((in[3] + in[nextrow+3]) >> 1);
720 in += nextrow; // skip a line
724 Sys_Error("GL_MipReduce: desired size already achieved\n");
728 void GL_UploadTexture (gltexture_t *glt)
730 int mip, width, height;
731 glBindTexture(GL_TEXTURE_2D, glt->texnum);
733 height = glt->height;
734 for (mip = 0;mip < MAXMIPS && glt->texels[mip];mip++)
735 glTexImage2D(GL_TEXTURE_2D, mip, glt->alpha ? 4 : 3, glt->texelsize[mip][0], glt->texelsize[mip][1], 0, GL_RGBA, GL_UNSIGNED_BYTE, glt->texels[mip]);
738 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
739 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
743 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
744 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
746 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
754 int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
757 int i, width2, height2, width3, height3, w, h, mip;
763 // LordHavoc: do a CRC to confirm the data really is the same as previous occurances.
764 crc = CRC_Block(data, width*height*bytesperpixel);
765 // see if the texture is already present
768 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
770 if (!strcmp (identifier, glt->identifier))
772 // LordHavoc: everyone hates cache mismatchs, so I fixed it
773 if (crc != glt->crc || width != glt->width || height != glt->height)
775 Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
776 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
777 //Sys_Error ("GL_LoadTexture: cache mismatch");
779 if ((gl_lerpimages.value != 0) != glt->lerped)
780 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
785 // LordHavoc: although this could be an else condition as it was in the original id code,
786 // it is more clear this way
787 // LordHavoc: check if there are still slots available
788 if (numgltextures >= MAX_GLTEXTURES)
789 Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES);
790 glt = &gltextures[numgltextures++];
792 strcpy (glt->identifier, identifier);
793 glt->texnum = texture_extension_number;
794 texture_extension_number++;
795 // LordHavoc: label to drop out of the loop into the setup code
796 GL_LoadTexture_setup:
797 // calculate power of 2 size
798 width2 = 1;while (width2 < width) width2 <<= 1;
799 height2 = 1;while (height2 < height) height2 <<= 1;
800 // calculate final size (mipmapped downward to this)
801 width3 = width2 >> (int) gl_picmip.value;
802 height3 = height2 >> (int) gl_picmip.value;
803 while (width3 > (int) gl_max_size.value) width3 >>= 1;
804 while (height3 > (int) gl_max_size.value) height3 >>= 1;
805 if (width3 < 1) width3 = 1;
806 if (height3 < 1) height3 = 1;
809 GL_AllocTexels(glt, width3, height3, mipmap);
810 glt->crc = crc; // LordHavoc: used to verify textures are identical
812 glt->height = height;
813 glt->mipmap = mipmap;
814 glt->bytesperpixel = bytesperpixel;
815 glt->lerped = gl_lerpimages.value != 0;
816 glt->alpha = false; // updated later
817 if (width == width3 && height == height3) // perfect match
819 if (bytesperpixel == 1) // 8bit
820 Image_Copy8bitRGBA(data, glt->texels[0], width*height, d_8to24table);
822 Image_CopyRGBAGamma(data, glt->texels[0], width*height);
824 else if (width == width2 && height == height2) // perfect match for top level, but needs to be reduced
827 temptexels2 = malloc(width2*height2*4); // scaleup buffer
828 if (bytesperpixel == 1) // 8bit
829 Image_Copy8bitRGBA(data, temptexels2, width*height, d_8to24table);
831 Image_CopyRGBAGamma(data, temptexels2, width*height);
832 while (width2 > width3 || height2 > height3)
834 w = width2;h = height2;
835 if (width2 > width3) width2 >>= 1;
836 if (height2 > height3) height2 >>= 1;
837 if (width2 <= width3 && height2 <= height3) // size achieved
838 GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3);
840 GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3);
847 // pre-scaleup buffer
848 temptexels = malloc(width*height*4);
849 if (bytesperpixel == 1) // 8bit
850 Image_Copy8bitRGBA(data, temptexels, width*height, d_8to24table);
852 Image_CopyRGBAGamma(data, temptexels, width*height);
853 if (width2 != width3 || height2 != height3) // reduced by gl_pic_mip or gl_max_size
856 temptexels2 = malloc(width2*height2*4); // scaleup buffer
857 GL_ResampleTexture(temptexels, width, height, temptexels2, width2, height2);
858 while (width2 > width3 || height2 > height3)
860 w = width2;h = height2;
861 if (width2 > width3) width2 >>= 1;
862 if (height2 > height3) height2 >>= 1;
863 if (width2 <= width3 && height2 <= height3) // size achieved
864 GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3);
866 GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3);
870 else // copy directly
871 GL_ResampleTexture(temptexels, width, height, glt->texels[0], width2, height2);
876 byte *in = glt->texels[0] + 3;
877 for (i = 0;i < width*height;i++, in += 4)
884 // this loop is skipped if there are no mipmaps to generate
885 for (mip = 1;mip < MAXMIPS && glt->texels[mip];mip++)
886 GL_MipReduce(glt->texels[mip-1], glt->texels[mip], glt->texelsize[mip-1][0], glt->texelsize[mip-1][1], 1, 1);
887 GL_UploadTexture(glt);
889 // if (bytesperpixel == 1) // 8bit
890 // GL_Upload8 (data, width, height, mipmap, alpha);
892 // GL_Upload32 (data, width, height, mipmap, true);
902 int GL_LoadPicTexture (qpic_t *pic)
904 return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
907 int GL_GetTextureSlots (int count)
909 gltexture_t *glt, *first;
911 first = glt = &gltextures[numgltextures];
914 glt->identifier[0] = 0;
915 glt->texnum = texture_extension_number++;
919 glt->bytesperpixel = 0;
923 return first->texnum;