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"};
6 cvar_t r_upload = {"r_upload", "1"};
8 int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR; //NEAREST;
9 int gl_filter_max = GL_LINEAR;
20 byte *texels[MAXMIPS];
21 unsigned short texelsize[MAXMIPS][2];
24 // LordHavoc: CRC to identify cache mismatchs
29 char lerped; // whether this texture was uploaded with or without interpolation
32 #define MAX_GLTEXTURES 4096
33 gltexture_t gltextures[MAX_GLTEXTURES];
39 int minimize, maximize;
43 {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
44 {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
45 {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
46 {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
47 {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
48 {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
56 void Draw_TextureMode_f (void)
63 for (i=0 ; i< 6 ; i++)
64 if (gl_filter_min == modes[i].minimize)
66 Con_Printf ("%s\n", modes[i].name);
69 Con_Printf ("current filter is unknown???\n");
73 for (i=0 ; i< 6 ; i++)
75 if (!Q_strcasecmp (modes[i].name, Cmd_Argv(1) ) )
80 Con_Printf ("bad filter name\n");
84 gl_filter_min = modes[i].minimize;
85 gl_filter_max = modes[i].maximize;
89 // change all the existing mipmap texture objects
90 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
94 glBindTexture(GL_TEXTURE_2D, glt->texnum);
95 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
96 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
101 extern int buildnumber;
103 char engineversion[40];
105 void GL_UploadTexture (gltexture_t *glt);
106 void gl_textures_start()
110 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
111 GL_UploadTexture(glt);
114 void gl_textures_shutdown()
118 void GL_Textures_Init (void)
120 Cvar_RegisterVariable (&gl_max_size);
121 Cvar_RegisterVariable (&gl_picmip);
122 Cvar_RegisterVariable (&gl_lerpimages);
123 Cvar_RegisterVariable (&r_upload);
128 // 3dfx can only handle 256 wide textures
129 if (!Q_strncasecmp ((char *)gl_renderer, "3dfx",4) || strstr((char *)gl_renderer, "Glide"))
130 Cvar_Set ("gl_max_size", "256");
132 Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
134 R_RegisterModule("GL_Textures", gl_textures_start, gl_textures_shutdown);
142 int GL_FindTexture (char *identifier)
147 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
149 if (!strcmp (identifier, glt->identifier))
150 return gltextures[i].texnum;
156 extern byte qgamma[];
158 // LordHavoc: gamma correction and improved resampling
159 void GL_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth)
161 int j, xi, oldx = 0, f, fstep, l1, l2, endx;
162 fstep = (int) (inwidth*65536.0f/outwidth);
164 for (j = 0,f = 0;j < outwidth;j++, f += fstep)
169 in += (xi - oldx) * 4;
176 *out++ = (byte) ((in[0] * l1 + in[4] * l2) >> 16);
177 *out++ = (byte) ((in[1] * l1 + in[5] * l2) >> 16);
178 *out++ = (byte) ((in[2] * l1 + in[6] * l2) >> 16);
179 *out++ = (byte) ((in[3] * l1 + in[7] * l2) >> 16);
180 // *out++ = qgamma[(byte) ((in[0] * l1 + in[4] * l2) >> 16)];
181 // *out++ = qgamma[(byte) ((in[1] * l1 + in[5] * l2) >> 16)];
182 // *out++ = qgamma[(byte) ((in[2] * l1 + in[6] * l2) >> 16)];
183 // *out++ = (byte) ((in[3] * l1 + in[7] * l2) >> 16) ;
185 else // last pixel of the line has no pixel to lerp to
191 // *out++ = qgamma[in[0]];
192 // *out++ = qgamma[in[1]];
193 // *out++ = qgamma[in[2]];
204 void GL_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight)
206 // LordHavoc: gamma correction and greatly improved resampling
207 if (gl_lerpimages.value)
209 int i, j, yi, oldy, f, fstep, l1, l2, endy = (inheight-1);
210 byte *inrow, *out, *row1, *row2;
212 fstep = (int) (inheight*65536.0f/outheight);
214 row1 = malloc(outwidth*4);
215 row2 = malloc(outwidth*4);
218 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
219 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
220 for (i = 0, f = 0;i < outheight;i++,f += fstep)
225 inrow = (byte *)indata + inwidth*4*yi;
227 memcpy(row1, row2, outwidth*4);
229 GL_ResampleTextureLerpLine (inrow, row1, inwidth, outwidth);
231 GL_ResampleTextureLerpLine (inrow + inwidth*4, row2, inwidth, outwidth);
233 memcpy(row2, row1, outwidth*4);
240 for (j = 0;j < outwidth;j++)
242 *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
243 *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
244 *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
245 *out++ = (byte) ((*row1++ * l1 + *row2++ * l2) >> 16);
250 else // last line has no pixels to lerp to
252 for (j = 0;j < outwidth;j++)
268 unsigned frac, fracstep;
269 byte *inrow, *out, *inpix;
272 fracstep = inwidth*0x10000/outwidth;
273 for (i=0 ; i<outheight ; i++)
275 inrow = (byte *)indata + inwidth*(i*inheight/outheight)*4;
276 frac = fracstep >> 1;
277 for (j=0 ; j<outwidth ; j+=4)
279 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
280 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
281 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
282 inpix = inrow + ((frac >> 14) & ~3);*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = qgamma[*inpix++];*out++ = *inpix++ ;frac += fracstep;
290 GL_Resample8BitTexture -- JACK
294 void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
297 unsigned char *inrow;
298 unsigned frac, fracstep;
300 fracstep = inwidth*0x10000/outwidth;
301 for (i=0 ; i<outheight ; i++, out += outwidth)
303 inrow = in + inwidth*(i*inheight/outheight);
304 frac = fracstep >> 1;
305 for (j=0 ; j<outwidth ; j+=4)
307 out[j ] = inrow[frac>>16];frac += fracstep;
308 out[j+1] = inrow[frac>>16];frac += fracstep;
309 out[j+2] = inrow[frac>>16];frac += fracstep;
310 out[j+3] = inrow[frac>>16];frac += fracstep;
321 Operates in place, quartering the size of the texture
325 void GL_MipMap (byte *in, int width, int height)
333 for (i=0 ; i<height ; i++, in+=width)
335 for (j=0 ; j<width ; j+=8, out+=4, in+=8)
337 out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
338 out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
339 out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
340 out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
350 Mipping for 8 bit textures
354 void GL_MipMap8Bit (byte *in, int width, int height)
357 unsigned short r,g,b;
358 byte *out, *at1, *at2, *at3, *at4;
362 for (i=0 ; i<height ; i++, in+=width)
364 for (j=0 ; j<width ; j+=2, out+=1, in+=2)
366 at1 = (byte *) (d_8to24table + in[0]);
367 at2 = (byte *) (d_8to24table + in[1]);
368 at3 = (byte *) (d_8to24table + in[width+0]);
369 at4 = (byte *) (d_8to24table + in[width+1]);
371 r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
372 g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
373 b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
375 out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
387 void GL_Upload32 (void *data, int width, int height, qboolean mipmap, qboolean alpha)
389 int samples, scaled_width, scaled_height, i;
390 byte *in, *out, *scaled;
392 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
394 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
397 scaled_width >>= (int)gl_picmip.value;
398 scaled_height >>= (int)gl_picmip.value;
400 if (scaled_width > gl_max_size.value)
401 scaled_width = gl_max_size.value;
402 if (scaled_height > gl_max_size.value)
403 scaled_height = gl_max_size.value;
409 for (i = 3;i < width*height*4;i += 4)
417 samples = alpha ? gl_alpha_format : gl_solid_format;
419 texels += scaled_width * scaled_height;
421 scaled = malloc(scaled_width*scaled_height*4);
422 if (scaled_width == width && scaled_height == height)
424 // LordHavoc: gamma correct while copying
426 out = (byte *)scaled;
427 for (i = 0;i < width*height;i++)
429 *out++ = qgamma[*in++];
430 *out++ = qgamma[*in++];
431 *out++ = qgamma[*in++];
436 GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
438 glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
444 while (scaled_width > 1 || scaled_height > 1)
446 GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
449 if (scaled_width < 1)
451 if (scaled_height < 1)
454 glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
460 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
461 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
465 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
466 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
471 void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap)
473 int scaled_width, scaled_height;
476 for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
478 for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
481 scaled_width >>= (int)gl_picmip.value;
482 scaled_height >>= (int)gl_picmip.value;
484 if (scaled_width > gl_max_size.value)
485 scaled_width = gl_max_size.value;
486 if (scaled_height > gl_max_size.value)
487 scaled_height = gl_max_size.value;
489 texels += scaled_width * scaled_height;
491 if (scaled_width == width && scaled_height == height)
495 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX , GL_UNSIGNED_BYTE, data);
498 scaled = malloc(scaled_width*scaled_height*4);
499 memcpy (scaled, data, width*height);
503 scaled = malloc(scaled_width*scaled_height*4);
504 GL_Resample8BitTexture (data, width, height, (void*) scaled, scaled_width, scaled_height);
507 glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
513 while (scaled_width > 1 || scaled_height > 1)
515 GL_MipMap8Bit ((byte *)scaled, scaled_width, scaled_height);
518 if (scaled_width < 1)
520 if (scaled_height < 1)
523 glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
531 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
532 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
536 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
537 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
543 extern qboolean VID_Is8bit();
551 void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
553 static unsigned *trans;
562 // if there are no transparent pixels, make it a 3 component
563 // texture even if it was specified as otherwise
567 for (i=0 ; i<s ; i++)
571 trans[i] = d_8to24table[p];
574 trans[i] = 0; // force to black
581 if (VID_Is8bit() && (data!=scrap_texels[0]))
583 GL_Upload8_EXT (data, width, height, mipmap);
592 // LordHavoc: dodge the copy if it will be uploaded as 8bit
593 if (VID_Is8bit() && (data!=scrap_texels[0]))
595 GL_Upload8_EXT (data, width, height, mipmap);
600 // Sys_Error ("GL_Upload8: s&3");
604 *outdata++ = d_8to24table[*indata++];
607 *outdata++ = d_8to24table[*indata++];
608 *outdata++ = d_8to24table[*indata++];
610 for (i = 0;i < s;i+=4)
612 *outdata++ = d_8to24table[*indata++];
613 *outdata++ = d_8to24table[*indata++];
614 *outdata++ = d_8to24table[*indata++];
615 *outdata++ = d_8to24table[*indata++];
619 GL_Upload32 (trans, width, height, mipmap, alpha);
624 void GL_AllocTexels(gltexture_t *glt, int width, int height, int mipmapped)
626 int i, w, h, size, done;
628 free(glt->texels[0]);
629 glt->texelsize[0][0] = width;
630 glt->texelsize[0][1] = height;
634 w = width;h = height;
637 for (i = 0;i < MAXMIPS;i++)
639 glt->texelsize[i][0] = w;
640 glt->texelsize[i][1] = h;
641 glt->texels[i] = (void *)size;
658 glt->texels[i++] = NULL;
659 glt->texels[0] = malloc(size);
660 for (i = 1;i < MAXMIPS && glt->texels[i];i++)
661 glt->texels[i] += (int) glt->texels[0];
665 glt->texels[0] = malloc(width*height*4);
666 for (i = 1;i < MAXMIPS;i++)
667 glt->texels[i] = NULL;
670 Sys_Error("GL_AllocTexels: out of memory\n");
673 // in can be the same as out
674 void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight)
676 int x, y, width2, height2, nextrow;
677 if (width > destwidth)
679 if (height > destheight)
683 height2 = height >> 1;
684 nextrow = width << 2;
685 for (y = 0;y < height2;y++)
687 for (x = 0;x < width2;x++)
689 out[0] = (byte) ((in[0] + in[4] + in[nextrow ] + in[nextrow+4]) >> 2);
690 out[1] = (byte) ((in[1] + in[5] + in[nextrow+1] + in[nextrow+5]) >> 2);
691 out[2] = (byte) ((in[2] + in[6] + in[nextrow+2] + in[nextrow+6]) >> 2);
692 out[3] = (byte) ((in[3] + in[7] + in[nextrow+3] + in[nextrow+7]) >> 2);
696 in += nextrow; // skip a line
703 for (y = 0;y < height;y++)
705 for (x = 0;x < width2;x++)
707 out[0] = (byte) ((in[0] + in[4]) >> 1);
708 out[1] = (byte) ((in[1] + in[5]) >> 1);
709 out[2] = (byte) ((in[2] + in[6]) >> 1);
710 out[3] = (byte) ((in[3] + in[7]) >> 1);
719 if (height > destheight)
722 height2 = height >> 1;
723 nextrow = width << 2;
724 for (y = 0;y < height2;y++)
726 for (x = 0;x < width;x++)
728 out[0] = (byte) ((in[0] + in[nextrow ]) >> 1);
729 out[1] = (byte) ((in[1] + in[nextrow+1]) >> 1);
730 out[2] = (byte) ((in[2] + in[nextrow+2]) >> 1);
731 out[3] = (byte) ((in[3] + in[nextrow+3]) >> 1);
735 in += nextrow; // skip a line
739 Sys_Error("GL_MipReduce: desired size already achieved\n");
743 void GL_UploadTexture (gltexture_t *glt)
745 int mip, width, height;
748 glBindTexture(GL_TEXTURE_2D, glt->texnum);
750 height = glt->height;
751 for (mip = 0;mip < MAXMIPS && glt->texels[mip];mip++)
752 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]);
755 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
756 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
760 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
761 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
763 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
771 int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
774 int i, width2, height2, width3, height3, w, h, mip;
780 // LordHavoc: do a CRC to confirm the data really is the same as previous occurances.
781 crc = CRC_Block(data, width*height*bytesperpixel);
782 // see if the texture is already present
785 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
787 if (!strcmp (identifier, glt->identifier))
789 // LordHavoc: everyone hates cache mismatchs, so I fixed it
790 if (crc != glt->crc || width != glt->width || height != glt->height)
792 Con_DPrintf("GL_LoadTexture: cache mismatch, replacing old texture\n");
793 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
794 //Sys_Error ("GL_LoadTexture: cache mismatch");
796 if ((gl_lerpimages.value != 0) != glt->lerped)
797 goto GL_LoadTexture_setup; // drop out with glt pointing to the texture to replace
802 // LordHavoc: although this could be an else condition as it was in the original id code,
803 // it is more clear this way
804 // LordHavoc: check if there are still slots available
805 if (numgltextures >= MAX_GLTEXTURES)
806 Sys_Error ("GL_LoadTexture: ran out of texture slots (%d)\n", MAX_GLTEXTURES);
807 glt = &gltextures[numgltextures++];
809 strcpy (glt->identifier, identifier);
810 glt->texnum = texture_extension_number;
811 texture_extension_number++;
812 // LordHavoc: label to drop out of the loop into the setup code
813 GL_LoadTexture_setup:
814 // calculate power of 2 size
815 width2 = 1;while (width2 < width) width2 <<= 1;
816 height2 = 1;while (height2 < height) height2 <<= 1;
817 // calculate final size (mipmapped downward to this)
818 width3 = width2 >> (int) gl_picmip.value;
819 height3 = height2 >> (int) gl_picmip.value;
820 while (width3 > (int) gl_max_size.value) width3 >>= 1;
821 while (height3 > (int) gl_max_size.value) height3 >>= 1;
822 if (width3 < 1) width3 = 1;
823 if (height3 < 1) height3 = 1;
826 GL_AllocTexels(glt, width3, height3, mipmap);
827 glt->crc = crc; // LordHavoc: used to verify textures are identical
829 glt->height = height;
830 glt->mipmap = mipmap;
831 glt->bytesperpixel = bytesperpixel;
832 glt->lerped = gl_lerpimages.value != 0;
833 glt->alpha = false; // updated later
834 if (width == width3 && height == height3) // perfect match
836 if (bytesperpixel == 1) // 8bit
837 Image_Copy8bitRGBA(data, glt->texels[0], width*height, d_8to24table);
839 Image_CopyRGBAGamma(data, glt->texels[0], width*height);
841 else if (width == width2 && height == height2) // perfect match for top level, but needs to be reduced
844 temptexels2 = malloc(width2*height2*4); // scaleup buffer
845 if (bytesperpixel == 1) // 8bit
846 Image_Copy8bitRGBA(data, temptexels2, width*height, d_8to24table);
848 Image_CopyRGBAGamma(data, temptexels2, width*height);
849 while (width2 > width3 || height2 > height3)
851 w = width2;h = height2;
852 if (width2 > width3) width2 >>= 1;
853 if (height2 > height3) height2 >>= 1;
854 if (width2 <= width3 && height2 <= height3) // size achieved
855 GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3);
857 GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3);
864 // pre-scaleup buffer
865 temptexels = malloc(width*height*4);
866 if (bytesperpixel == 1) // 8bit
867 Image_Copy8bitRGBA(data, temptexels, width*height, d_8to24table);
869 Image_CopyRGBAGamma(data, temptexels, width*height);
870 if (width2 != width3 || height2 != height3) // reduced by gl_pic_mip or gl_max_size
873 temptexels2 = malloc(width2*height2*4); // scaleup buffer
874 GL_ResampleTexture(temptexels, width, height, temptexels2, width2, height2);
875 while (width2 > width3 || height2 > height3)
877 w = width2;h = height2;
878 if (width2 > width3) width2 >>= 1;
879 if (height2 > height3) height2 >>= 1;
880 if (width2 <= width3 && height2 <= height3) // size achieved
881 GL_MipReduce(temptexels2, glt->texels[0], w, h, width3, height3);
883 GL_MipReduce(temptexels2, temptexels2, w, h, width3, height3);
887 else // copy directly
888 GL_ResampleTexture(temptexels, width, height, glt->texels[0], width2, height2);
893 byte *in = glt->texels[0] + 3;
894 for (i = 0;i < width*height;i++, in += 4)
901 // this loop is skipped if there are no mipmaps to generate
902 for (mip = 1;mip < MAXMIPS && glt->texels[mip];mip++)
903 GL_MipReduce(glt->texels[mip-1], glt->texels[mip], glt->texelsize[mip-1][0], glt->texelsize[mip-1][1], 1, 1);
904 GL_UploadTexture(glt);
906 // if (bytesperpixel == 1) // 8bit
907 // GL_Upload8 (data, width, height, mipmap, alpha);
909 // GL_Upload32 (data, width, height, mipmap, true);
919 int GL_LoadPicTexture (qpic_t *pic)
921 return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
924 int GL_GetTextureSlots (int count)
926 gltexture_t *glt, *first;
928 first = glt = &gltextures[numgltextures];
931 glt->identifier[0] = 0;
932 glt->texnum = texture_extension_number++;
936 glt->bytesperpixel = 0;
940 return first->texnum;