mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2025-02-23 04:21:22 +00:00
Added support for my extended miptex stuff for high-colour map textures.
This commit is contained in:
parent
c2c9a68ff1
commit
27168ec47b
6 changed files with 342 additions and 92 deletions
|
@ -560,6 +560,90 @@ qboolean Mod_CheckFullbrights (byte *pixels, int count)
|
|||
return false;
|
||||
}
|
||||
|
||||
static texture_t *Mod_LoadMipTex(miptex_t *mt, byte *lumpend, enum srcformat *fmt, unsigned int *width, unsigned int *height, unsigned int *pixelbytes)
|
||||
{
|
||||
//if offsets[0] is 0, then we've no legacy data (offsets[3] signifies the end of the extension data.
|
||||
byte *extdata;
|
||||
texture_t *tx;
|
||||
byte *srcdata = NULL;
|
||||
size_t sz;
|
||||
|
||||
if (!mt->offsets[0]) //the legacy data was omitted. we may still have block-compression though.
|
||||
extdata = (byte*)(mt+1);
|
||||
else if (mt->offsets[0] == sizeof(miptex_t) &&
|
||||
mt->offsets[1] == mt->offsets[0]+(mt->width>>0)*(mt->height>>0) &&
|
||||
mt->offsets[2] == mt->offsets[1]+(mt->width>>1)*(mt->height>>1) &&
|
||||
mt->offsets[3] == mt->offsets[2]+(mt->width>>2)*(mt->height>>2))
|
||||
{ //miptex makes sense and matches the standard 4-mip-levels.
|
||||
extdata = (byte*)mt + mt->offsets[3]+(mt->width>>3)*(mt->height>>3);
|
||||
//FIXME: halflife - leshort=256, palette[256][3].
|
||||
//extdata += 2+256*3;
|
||||
}
|
||||
else //the numbers don't match what we expect... something weird is going on here... don't misinterpret it.
|
||||
extdata = lumpend;
|
||||
|
||||
if (extdata+4 <= lumpend && extdata[0] == 0 && extdata[1]==0xfb && extdata[2]==0x2b && extdata[3]==0xaf)
|
||||
for (extdata+=4; extdata+8 < lumpend; extdata += sz)
|
||||
{
|
||||
sz = (extdata[0]<<0)|(extdata[1]<<8)|(extdata[2]<<16)|(extdata[3]<<24);
|
||||
if (sz < 8 || sz > lumpend-extdata) break; //bad! bad! bad!
|
||||
else if (sz <= 16) continue; //nope, no idea
|
||||
|
||||
*fmt = TexMgr_FormatForCode((char*)extdata+4);
|
||||
if (*fmt == SRC_EXTERNAL)
|
||||
continue; //nope, no idea
|
||||
|
||||
*width = (extdata[8]<<0)|(extdata[9]<<8)|(extdata[10]<<16)|(extdata[11]<<24);
|
||||
*height = (extdata[12]<<0)|(extdata[13]<<8)|(extdata[14]<<16)|(extdata[15]<<24);
|
||||
|
||||
if (*width != TexMgr_SafeTextureSize(*width) || *width != TexMgr_SafeTextureSize(*width))
|
||||
continue; //nope, can't use that. drivers are too lame (or gl_max_size is too low).
|
||||
|
||||
*pixelbytes = TexMgr_ImageSize(*width, *height, *fmt);
|
||||
if (16+*pixelbytes == sz)
|
||||
srcdata = extdata+16;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!srcdata)
|
||||
{ //no replacements, load the 8bit data.
|
||||
*fmt = SRC_INDEXED;
|
||||
*width = mt->width;
|
||||
*height = mt->height;
|
||||
*pixelbytes = mt->width*mt->height;
|
||||
if (LittleLong (mt->offsets[0]))
|
||||
srcdata = (byte*)mt+LittleLong(mt->offsets[0]);
|
||||
}
|
||||
|
||||
tx = (texture_t *) Hunk_AllocName (sizeof(texture_t) + *pixelbytes, loadname );
|
||||
memcpy (tx->name, mt->name, sizeof(tx->name));
|
||||
tx->name[sizeof(tx->name)-1] = 0; //just in case...
|
||||
tx->width = mt->width;
|
||||
tx->height = mt->height;
|
||||
|
||||
if (srcdata)
|
||||
{
|
||||
// ericw -- check for pixels extending past the end of the lump.
|
||||
// appears in the wild; e.g. jam2_tronyn.bsp (func_mapjam2),
|
||||
// kellbase1.bsp (quoth), and can lead to a segfault if we read past
|
||||
// the end of the .bsp file buffer
|
||||
if ((srcdata + *pixelbytes) > lumpend)
|
||||
{
|
||||
Con_DPrintf("Texture %s extends past end of lump\n", mt->name);
|
||||
*pixelbytes = q_max(0, lumpend - srcdata);
|
||||
}
|
||||
|
||||
memcpy ( tx+1, srcdata, *pixelbytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t x,y;
|
||||
for(y=0;y<tx->width;y++)
|
||||
for(x=0;x<tx->width;x++)
|
||||
((byte*)(tx+1))[y*tx->width+x] = (((x>>2)^(y>>2))&1)?6:2;
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
/*
|
||||
=================
|
||||
Mod_LoadTextures
|
||||
|
@ -567,7 +651,7 @@ Mod_LoadTextures
|
|||
*/
|
||||
void Mod_LoadTextures (lump_t *l)
|
||||
{
|
||||
int i, j, pixels, num, maxanim, altmax;
|
||||
int i, j, num, maxanim, altmax;
|
||||
miptex_t *mt;
|
||||
texture_t *tx, *tx2;
|
||||
texture_t *anims[10];
|
||||
|
@ -583,6 +667,9 @@ void Mod_LoadTextures (lump_t *l)
|
|||
extern byte *hunk_base;
|
||||
//johnfitz
|
||||
qboolean malloced; //spike
|
||||
enum srcformat fmt; //spike
|
||||
unsigned int imgwidth, imgheight, imgpixels;
|
||||
unsigned int mipend;
|
||||
|
||||
//johnfitz -- don't return early if no textures; still need to create dummy texture
|
||||
if (!l->filelen)
|
||||
|
@ -602,68 +689,37 @@ void Mod_LoadTextures (lump_t *l)
|
|||
loadmodel->numtextures = nummiptex + 2; //johnfitz -- need 2 dummy texture chains for missing textures
|
||||
loadmodel->textures = (texture_t **) Hunk_AllocName (loadmodel->numtextures * sizeof(*loadmodel->textures) , loadname);
|
||||
|
||||
for (i=0 ; i<nummiptex ; i++)
|
||||
//spike -- rewrote this loop to run backwards (to make it easier to track the end of the miptex) and added handling for extra texture block compression.
|
||||
for (i = nummiptex, mipend=l->filelen; i --> 0; )
|
||||
{
|
||||
m->dataofs[i] = LittleLong(m->dataofs[i]);
|
||||
if (m->dataofs[i] == -1)
|
||||
continue;
|
||||
if (m->dataofs[i] >= mipend)
|
||||
mipend = l->filelen; //o.O something weird!
|
||||
mt = (miptex_t *)((byte *)m + m->dataofs[i]);
|
||||
mt->width = LittleLong (mt->width);
|
||||
mt->height = LittleLong (mt->height);
|
||||
// for (j=0 ; j<MIPLEVELS ; j++)
|
||||
// mt->offsets[j] = LittleLong (mt->offsets[j]);
|
||||
for (j=0 ; j<MIPLEVELS ; j++)
|
||||
mt->offsets[j] = LittleLong (mt->offsets[j]);
|
||||
|
||||
if ( (mt->width & 15) || (mt->height & 15) )
|
||||
Sys_Error ("Texture %s is not 16 aligned", mt->name);
|
||||
// spike -- quakespasm doesn't use the submips anyway
|
||||
pixels = mt->width*mt->height;
|
||||
//pixels = mt->width*mt->height/64*85;
|
||||
|
||||
tx = (texture_t *) Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
|
||||
tx = Mod_LoadMipTex(mt, (mod_base + l->fileofs + mipend), &fmt, &imgwidth, &imgheight, &imgpixels);
|
||||
loadmodel->textures[i] = tx;
|
||||
|
||||
memcpy (tx->name, mt->name, sizeof(tx->name));
|
||||
tx->width = mt->width;
|
||||
tx->height = mt->height;
|
||||
// for (j=0 ; j<MIPLEVELS ; j++)
|
||||
// tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
|
||||
// the pixels immediately follow the structures
|
||||
|
||||
if (!LittleLong (mt->offsets[0]))
|
||||
{ // spike -- support tyrlight-ericw's -notex argument to avoid gpl violations from embedded textures
|
||||
size_t x,y;
|
||||
for(y=0;y<tx->width;y++)
|
||||
for(x=0;x<tx->width;x++)
|
||||
((byte*)(tx+1))[y*tx->width+x] = (((x>>2)^(y>>2))&1)?6:2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ericw -- check for pixels extending past the end of the lump.
|
||||
// appears in the wild; e.g. jam2_tronyn.bsp (func_mapjam2),
|
||||
// kellbase1.bsp (quoth), and can lead to a segfault if we read past
|
||||
// the end of the .bsp file buffer
|
||||
if (((byte*)(mt+1) + pixels) > (mod_base + l->fileofs + l->filelen))
|
||||
{
|
||||
Con_DPrintf("Texture %s extends past end of lump\n", mt->name);
|
||||
pixels = q_max(0, (mod_base + l->fileofs + l->filelen) - (byte*)(mt+1));
|
||||
}
|
||||
|
||||
//spike -- this is actually a pointless waste of memory.
|
||||
//its not like this data will actually be used beyond this function in any gl renderer.
|
||||
//this makes copying it pointless
|
||||
//which in turn makes the pointer-to-array-of-pointers-to-texture a bit silly.
|
||||
memcpy ( tx+1, mt+1, pixels);
|
||||
}
|
||||
|
||||
tx->update_warp = false; //johnfitz
|
||||
tx->warpimage = NULL; //johnfitz
|
||||
tx->fullbright = NULL; //johnfitz
|
||||
|
||||
mipend = m->dataofs[i];
|
||||
|
||||
//johnfitz -- lots of changes
|
||||
if (!isDedicated) //no texture uploading for dedicated server
|
||||
{
|
||||
if (!q_strncasecmp(tx->name,"sky",3)) //sky texture //also note -- was Q_strncmp, changed to match qbsp
|
||||
Sky_LoadTexture (tx);
|
||||
Sky_LoadTexture (tx, fmt, imgwidth, imgheight);
|
||||
else if (tx->name[0] == '*') //warping texture
|
||||
{
|
||||
//external textures -- first look in "textures/mapname/" then look in "textures/"
|
||||
|
@ -688,8 +744,8 @@ void Mod_LoadTextures (lump_t *l)
|
|||
{
|
||||
q_snprintf (texturename, sizeof(texturename), "%s:%s", loadmodel->name, tx->name);
|
||||
offset = (src_offset_t)(mt+1) - (src_offset_t)mod_base;
|
||||
tx->gltexture = TexMgr_LoadImage (loadmodel, texturename, tx->width, tx->height,
|
||||
SRC_INDEXED, (byte *)(tx+1), loadmodel->name, offset, TEXPREF_NONE);
|
||||
tx->gltexture = TexMgr_LoadImage (loadmodel, texturename, imgwidth, imgheight,
|
||||
fmt, (byte *)(tx+1), loadmodel->name, offset, TEXPREF_NONE);
|
||||
}
|
||||
|
||||
//now create the warpimage, using dummy data from the hunk to create the initial image
|
||||
|
@ -749,18 +805,18 @@ void Mod_LoadTextures (lump_t *l)
|
|||
{
|
||||
q_snprintf (texturename, sizeof(texturename), "%s:%s", loadmodel->name, tx->name);
|
||||
offset = (src_offset_t)(mt+1) - (src_offset_t)mod_base;
|
||||
if (Mod_CheckFullbrights ((byte *)(tx+1), pixels))
|
||||
if (fmt == SRC_INDEXED && Mod_CheckFullbrights ((byte *)(tx+1), imgpixels))
|
||||
{
|
||||
tx->gltexture = TexMgr_LoadImage (loadmodel, texturename, tx->width, tx->height,
|
||||
SRC_INDEXED, (byte *)(tx+1), loadmodel->name, offset, TEXPREF_MIPMAP | TEXPREF_NOBRIGHT | extraflags);
|
||||
tx->gltexture = TexMgr_LoadImage (loadmodel, texturename, imgwidth, imgheight,
|
||||
fmt, (byte *)(tx+1), loadmodel->name, offset, TEXPREF_MIPMAP | TEXPREF_NOBRIGHT | extraflags);
|
||||
q_snprintf (texturename, sizeof(texturename), "%s:%s_glow", loadmodel->name, tx->name);
|
||||
tx->fullbright = TexMgr_LoadImage (loadmodel, texturename, tx->width, tx->height,
|
||||
SRC_INDEXED, (byte *)(tx+1), loadmodel->name, offset, TEXPREF_MIPMAP | TEXPREF_FULLBRIGHT | extraflags);
|
||||
tx->fullbright = TexMgr_LoadImage (loadmodel, texturename, imgwidth, imgheight,
|
||||
fmt, (byte *)(tx+1), loadmodel->name, offset, TEXPREF_MIPMAP | TEXPREF_FULLBRIGHT | extraflags);
|
||||
}
|
||||
else
|
||||
{
|
||||
tx->gltexture = TexMgr_LoadImage (loadmodel, texturename, tx->width, tx->height,
|
||||
SRC_INDEXED, (byte *)(tx+1), loadmodel->name, offset, TEXPREF_MIPMAP | extraflags);
|
||||
tx->gltexture = TexMgr_LoadImage (loadmodel, texturename, imgwidth, imgheight,
|
||||
fmt, (byte *)(tx+1), loadmodel->name, offset, TEXPREF_MIPMAP | extraflags);
|
||||
}
|
||||
}
|
||||
if (malloced)
|
||||
|
|
|
@ -97,43 +97,55 @@ Sky_LoadTexture
|
|||
A sky texture is 256*128, with the left side being a masked overlay
|
||||
==============
|
||||
*/
|
||||
void Sky_LoadTexture (texture_t *mt)
|
||||
void Sky_LoadTexture (texture_t *mt, enum srcformat fmt, unsigned int srcwidth, unsigned int height)
|
||||
{
|
||||
char texturename[64];
|
||||
int i, j, p, r, g, b, count;
|
||||
int i, p, r, g, b, count;
|
||||
byte *src;
|
||||
static byte front_data[128*128]; //FIXME: Hunk_Alloc
|
||||
static byte back_data[128*128]; //FIXME: Hunk_Alloc
|
||||
byte *front_data;
|
||||
byte *back_data;
|
||||
unsigned *rgba;
|
||||
int rows, columns;
|
||||
int bb,bw,bh;
|
||||
int width = srcwidth/2;
|
||||
|
||||
TexMgr_BlockSize(fmt, &bb, &bw, &bh);
|
||||
columns = (width+bw-1) / bw;
|
||||
rows = (height+bh-1) / bh;
|
||||
|
||||
front_data = Hunk_AllocName (bb*columns*rows*2, "skytex");
|
||||
back_data = front_data+bb*columns*rows;
|
||||
|
||||
src = (byte *)(mt+1);
|
||||
|
||||
// extract back layer and upload
|
||||
for (i=0 ; i<128 ; i++)
|
||||
for (j=0 ; j<128 ; j++)
|
||||
back_data[(i*128) + j] = src[i*256 + j + 128];
|
||||
for (i=0 ; i<rows ; i++)
|
||||
memcpy(back_data+bb*i*columns, src+bb*(i*columns*2 + columns), columns*bb);
|
||||
|
||||
q_snprintf(texturename, sizeof(texturename), "%s:%s_back", loadmodel->name, mt->name);
|
||||
solidskytexture = TexMgr_LoadImage (loadmodel, texturename, 128, 128, SRC_INDEXED, back_data, "", (src_offset_t)back_data, TEXPREF_NONE);
|
||||
solidskytexture = TexMgr_LoadImage (loadmodel, texturename, width, height, fmt, back_data, "", (src_offset_t)back_data, TEXPREF_NONE);
|
||||
|
||||
// extract front layer and upload
|
||||
for (i=0 ; i<128 ; i++)
|
||||
for (j=0 ; j<128 ; j++)
|
||||
for (i=0 ; i<rows ; i++)
|
||||
memcpy(front_data+bb*i*columns, src+bb*(i*columns*2), columns*bb);
|
||||
if (fmt == SRC_INDEXED)
|
||||
{ //the lame texmgr only knows one transparent index...
|
||||
for (i=0 ; i<width*height ; i++)
|
||||
{
|
||||
front_data[(i*128) + j] = src[i*256 + j];
|
||||
if (front_data[(i*128) + j] == 0)
|
||||
front_data[(i*128) + j] = 255;
|
||||
if (front_data[i] == 0)
|
||||
front_data[i] = 255;
|
||||
}
|
||||
|
||||
}
|
||||
q_snprintf(texturename, sizeof(texturename), "%s:%s_front", loadmodel->name, mt->name);
|
||||
alphaskytexture = TexMgr_LoadImage (loadmodel, texturename, 128, 128, SRC_INDEXED, front_data, "", (src_offset_t)front_data, TEXPREF_ALPHA);
|
||||
alphaskytexture = TexMgr_LoadImage (loadmodel, texturename, width, height, fmt, front_data, "", (src_offset_t)front_data, TEXPREF_ALPHA);
|
||||
|
||||
// calculate r_fastsky color based on average of all opaque foreground colors
|
||||
// calculate r_fastsky color based on average of all opaque foreground colors, if we can.
|
||||
r = g = b = count = 0;
|
||||
for (i=0 ; i<128 ; i++)
|
||||
for (j=0 ; j<128 ; j++)
|
||||
if (fmt == SRC_INDEXED)
|
||||
{
|
||||
for (i=0 ; i<width*height ; i++)
|
||||
{
|
||||
p = src[i*256 + j];
|
||||
p = src[i];
|
||||
if (p != 0)
|
||||
{
|
||||
rgba = &d_8to24table[p];
|
||||
|
@ -143,6 +155,7 @@ void Sky_LoadTexture (texture_t *mt)
|
|||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
skyflatcolor[0] = (float)r/(count*255);
|
||||
skyflatcolor[1] = (float)g/(count*255);
|
||||
skyflatcolor[2] = (float)b/(count*255);
|
||||
|
|
|
@ -47,6 +47,56 @@ unsigned int d_8to24table_conchars[256];
|
|||
unsigned int d_8to24table_shirt[256];
|
||||
unsigned int d_8to24table_pants[256];
|
||||
|
||||
static struct
|
||||
{
|
||||
const char *mipextname;
|
||||
int internalformat;
|
||||
int format;
|
||||
int type; //for non-compressed formats
|
||||
int blockbytes;
|
||||
int blockwidth;
|
||||
int blockheight;
|
||||
qboolean *supported;
|
||||
} compressedformats[] =
|
||||
{
|
||||
{NULL}, //SRC_INDEXED
|
||||
{NULL}, //SRC_LIGHTMAP
|
||||
{NULL}, //SRC_RGBA
|
||||
{NULL}, //SRC_EXTERNAL
|
||||
|
||||
{"RGBA", GL_RGBA,GL_RGBA,GL_UNSIGNED_INT_8_8_8_8_REV, 4, 1, 1, NULL},
|
||||
{"RGB", GL_RGB,GL_RGB,GL_UNSIGNED_BYTE, 3, 1, 1, NULL},
|
||||
{"565", GL_RGB565,GL_RGB,GL_UNSIGNED_SHORT_5_6_5, 2, 1, 1, NULL},
|
||||
{"4444", GL_RGBA4,GL_RGBA,GL_UNSIGNED_SHORT_4_4_4_4, 2, 1, 1, NULL},
|
||||
{"5551", GL_RGB5_A1,GL_RGBA,GL_UNSIGNED_SHORT_5_5_5_1, 2, 1, 1, NULL},
|
||||
{"LUM8", GL_LUMINANCE8,GL_LUMINANCE,GL_UNSIGNED_BYTE, 1, 1, 1, NULL},
|
||||
{"EXP5", GL_RGB9_E5,GL_RGB,GL_UNSIGNED_INT_5_9_9_9_REV, 4, 1, 1, &gl_texture_astc},
|
||||
{"BC1", GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,0,0, 8, 4, 4, &gl_texture_s3tc},
|
||||
{"BC2", GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,0,0, 16, 4, 4, &gl_texture_s3tc},
|
||||
{"BC3", GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,0,0, 16, 4, 4, &gl_texture_s3tc},
|
||||
{"BC4", GL_COMPRESSED_RED_RGTC1,0,0, 8, 4, 4, &gl_texture_rgtc},
|
||||
{"BC5", GL_COMPRESSED_RG_RGTC2,0,0, 16, 4, 4, &gl_texture_rgtc},
|
||||
{"BC6", GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,0,0, 16, 4, 4, &gl_texture_bptc},
|
||||
{"BC7", GL_COMPRESSED_RGBA_BPTC_UNORM,0,0, 16, 4, 4, &gl_texture_bptc},
|
||||
{"ETC1", GL_COMPRESSED_RGB8_ETC2,0,0, 8, 4, 4, &gl_texture_etc2},
|
||||
{"ETC2", GL_COMPRESSED_RGB8_ETC2,0,0, 8, 4, 4, &gl_texture_etc2},
|
||||
{"ETCP", GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,0,0,8, 4, 4, &gl_texture_etc2},
|
||||
{"ETCA", GL_COMPRESSED_RGBA8_ETC2_EAC,0,0, 16, 4, 4, &gl_texture_etc2},
|
||||
{"AST4", GL_COMPRESSED_RGBA_ASTC_4x4_KHR,0,0, 16, 4, 4, &gl_texture_astc},
|
||||
{"AS54", GL_COMPRESSED_RGBA_ASTC_5x4_KHR,0,0, 16, 4, 4, &gl_texture_astc},
|
||||
{"AST5", GL_COMPRESSED_RGBA_ASTC_5x5_KHR,0,0, 16, 5, 5, &gl_texture_astc},
|
||||
{"AS65", GL_COMPRESSED_RGBA_ASTC_6x5_KHR,0,0, 16, 4, 4, &gl_texture_astc},
|
||||
{"AST6", GL_COMPRESSED_RGBA_ASTC_6x6_KHR,0,0, 16, 6, 6, &gl_texture_astc},
|
||||
{"AS85", GL_COMPRESSED_RGBA_ASTC_8x5_KHR,0,0, 16, 4, 4, &gl_texture_astc},
|
||||
{"AS86", GL_COMPRESSED_RGBA_ASTC_8x6_KHR,0,0, 16, 4, 4, &gl_texture_astc},
|
||||
{"AST8", GL_COMPRESSED_RGBA_ASTC_8x8_KHR,0,0, 16, 8, 8, &gl_texture_astc},
|
||||
{"AS05", GL_COMPRESSED_RGBA_ASTC_10x5_KHR,0,0, 16, 4, 4, &gl_texture_astc},
|
||||
{"AS06", GL_COMPRESSED_RGBA_ASTC_10x6_KHR,0,0, 16, 4, 4, &gl_texture_astc},
|
||||
{"AS08", GL_COMPRESSED_RGBA_ASTC_10x8_KHR,0,0, 16, 4, 4, &gl_texture_astc},
|
||||
{"AST0", GL_COMPRESSED_RGBA_ASTC_10x10_KHR,0,0, 16, 8, 8, &gl_texture_astc},
|
||||
{"AST2", GL_COMPRESSED_RGBA_ASTC_12x12_KHR,0,0, 16, 8, 8, &gl_texture_astc},
|
||||
};
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
|
||||
|
@ -1096,6 +1146,134 @@ static void TexMgr_LoadImage32 (gltexture_t *glt, unsigned *data)
|
|||
TexMgr_SetFilterModes (glt);
|
||||
}
|
||||
|
||||
void TexMgr_BlockSize (enum srcformat format, int *bytes, int *width, int *height)
|
||||
{
|
||||
*width = 1;
|
||||
*height = 1;
|
||||
switch(format)
|
||||
{
|
||||
case SRC_RGBA:
|
||||
*bytes = 4;
|
||||
break;
|
||||
case SRC_LIGHTMAP:
|
||||
*bytes = lightmap_bytes;
|
||||
break;
|
||||
case SRC_INDEXED:
|
||||
*bytes = 1;
|
||||
break;
|
||||
case SRC_EXTERNAL:
|
||||
*bytes = 0;
|
||||
break;
|
||||
default:
|
||||
*bytes = compressedformats[format].blockbytes;
|
||||
*width = compressedformats[format].blockwidth;
|
||||
*height = compressedformats[format].blockheight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
size_t TexMgr_ImageSize (int width, int height, enum srcformat format)
|
||||
{
|
||||
int miplevel, mipwidth, mipheight;
|
||||
size_t mipbytes = 0, blockbytes;
|
||||
unsigned int blockwidth, blockheight;
|
||||
switch(format)
|
||||
{
|
||||
case SRC_RGBA:
|
||||
return width*height*4;
|
||||
case SRC_LIGHTMAP:
|
||||
return width*height*lightmap_bytes;
|
||||
case SRC_INDEXED:
|
||||
return width*height;
|
||||
case SRC_EXTERNAL: //panic
|
||||
Con_Printf("TexMgr_ImageCompressedSize called for SRC_EXTERNAL\n");
|
||||
return 0;
|
||||
default:
|
||||
//a compressed format with multiple mip levels in it
|
||||
blockbytes = compressedformats[format].blockbytes;
|
||||
blockwidth = compressedformats[format].blockwidth;
|
||||
blockheight = compressedformats[format].blockheight;
|
||||
for (miplevel = 0; ; miplevel++)
|
||||
{
|
||||
mipwidth = width >> miplevel;
|
||||
mipheight = height >> miplevel;
|
||||
if (!mipwidth && !mipheight)
|
||||
break;
|
||||
mipwidth = q_max(1,mipwidth); //include the 1*1 mip with non-square textures.
|
||||
mipheight = q_max(1,mipheight);
|
||||
mipbytes += blockbytes*((mipwidth+blockwidth-1)/blockwidth)*((mipheight+blockheight-1)/blockheight);
|
||||
}
|
||||
return mipbytes;
|
||||
}
|
||||
}
|
||||
enum srcformat TexMgr_FormatForCode (const char *code)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(compressedformats)/sizeof(compressedformats[0]); i++)
|
||||
{
|
||||
if (!compressedformats[i].mipextname)
|
||||
continue;
|
||||
if (!strncasecmp(code, compressedformats[i].mipextname, 4))
|
||||
return i;
|
||||
}
|
||||
return SRC_EXTERNAL;
|
||||
}
|
||||
static void TexMgr_LoadImageCompressed (gltexture_t *glt, byte *data)
|
||||
{
|
||||
int internalformat, format, type, miplevel, mipwidth, mipheight, picmip;
|
||||
size_t mipbytes, blockbytes;
|
||||
unsigned int blockwidth, blockheight;
|
||||
|
||||
internalformat = compressedformats[glt->source_format].internalformat;
|
||||
format = compressedformats[glt->source_format].format;
|
||||
type = compressedformats[glt->source_format].type;
|
||||
blockbytes = compressedformats[glt->source_format].blockbytes;
|
||||
blockwidth = compressedformats[glt->source_format].blockwidth;
|
||||
blockheight = compressedformats[glt->source_format].blockheight;
|
||||
|
||||
//no premultiply support.
|
||||
//no npot fallback support
|
||||
|
||||
// mipmap down
|
||||
picmip = ((glt->flags & TEXPREF_NOPICMIP) || !(glt->flags & TEXPREF_MIPMAP)) ? 0 : q_max((int)gl_picmip.value, 0);
|
||||
|
||||
//make sure the picmip level is not bigger than the number of mips that we have available...
|
||||
while (picmip && (!(glt->width>>picmip) || !(glt->height>>picmip)))
|
||||
picmip--;
|
||||
|
||||
if (type && blockbytes < 4)
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //makes stuff work more reliably, if slower.
|
||||
|
||||
//upload each mip level in turn.
|
||||
GL_Bind (glt);
|
||||
for (miplevel = 0; ; miplevel++)
|
||||
{
|
||||
mipwidth = glt->width >> miplevel;
|
||||
mipheight = glt->height >> miplevel;
|
||||
if (!mipwidth && !mipheight)
|
||||
break;
|
||||
mipwidth = q_max(1,mipwidth); //include the 1*1 mip with non-square textures.
|
||||
mipheight = q_max(1,mipheight);
|
||||
mipbytes = blockbytes*((mipwidth+blockwidth-1)/blockwidth)*((mipheight+blockheight-1)/blockheight);
|
||||
if (miplevel-picmip >= 0)
|
||||
{
|
||||
if (type)
|
||||
glTexImage2D(GL_TEXTURE_2D, miplevel-picmip, internalformat, mipwidth, mipheight, 0, format, type, data);
|
||||
else
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, miplevel-picmip, internalformat, mipwidth, mipheight, 0, mipbytes, data);
|
||||
}
|
||||
data += mipbytes;
|
||||
|
||||
if (!(glt->flags & TEXPREF_MIPMAP))
|
||||
break;
|
||||
}
|
||||
|
||||
if (type && blockbytes < 4)
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); //back to opengl's default.
|
||||
|
||||
// set filter modes
|
||||
TexMgr_SetFilterModes (glt);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
TexMgr_LoadImage8 -- handles 8bit source data, then passes it to LoadImage32
|
||||
|
@ -1225,21 +1403,10 @@ gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int
|
|||
return NULL;
|
||||
|
||||
// cache check
|
||||
switch (format)
|
||||
{
|
||||
case SRC_INDEXED:
|
||||
crc = CRC_Block(data, width * height);
|
||||
break;
|
||||
case SRC_LIGHTMAP:
|
||||
crc = CRC_Block(data, width * height * lightmap_bytes);
|
||||
break;
|
||||
case SRC_RGBA:
|
||||
crc = CRC_Block(data, width * height * 4);
|
||||
break;
|
||||
case SRC_EXTERNAL:
|
||||
default: /* not reachable but avoids compiler warnings */
|
||||
if (format == SRC_EXTERNAL)
|
||||
crc = 0;
|
||||
}
|
||||
else
|
||||
crc = CRC_Block(data, TexMgr_ImageSize(width, height, format));
|
||||
if ((flags & TEXPREF_OVERWRITE) && (glt = TexMgr_FindTexture (owner, name)))
|
||||
{
|
||||
if (glt->source_crc == crc)
|
||||
|
@ -1295,6 +1462,9 @@ gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int
|
|||
case SRC_RGBA:
|
||||
TexMgr_LoadImage32 (glt, (unsigned *)data);
|
||||
break;
|
||||
default:
|
||||
TexMgr_LoadImageCompressed (glt, data);
|
||||
break;
|
||||
}
|
||||
|
||||
Hunk_FreeToLowMark(mark);
|
||||
|
@ -1335,12 +1505,8 @@ void TexMgr_ReloadImage (gltexture_t *glt, int shirt, int pants)
|
|||
if (!f)
|
||||
goto invalid;
|
||||
fseek (f, glt->source_offset, SEEK_CUR);
|
||||
size = (long) (glt->source_width * glt->source_height);
|
||||
/* should be SRC_INDEXED, but no harm being paranoid: */
|
||||
if (glt->source_format == SRC_RGBA)
|
||||
size *= 4;
|
||||
else if (glt->source_format == SRC_LIGHTMAP)
|
||||
size *= lightmap_bytes;
|
||||
|
||||
size = TexMgr_ImageSize(glt->source_width, glt->source_height, glt->source_format);
|
||||
data = (byte *) Hunk_Alloc (size);
|
||||
fread (data, 1, size, f);
|
||||
fclose (f);
|
||||
|
@ -1430,6 +1596,9 @@ invalid:
|
|||
case SRC_RGBA:
|
||||
TexMgr_LoadImage32 (glt, (unsigned *)data);
|
||||
break;
|
||||
default:
|
||||
TexMgr_LoadImageCompressed (glt, data);
|
||||
break;
|
||||
}
|
||||
|
||||
if (malloced)
|
||||
|
|
|
@ -40,7 +40,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define TEXPREF_WARPIMAGE 0x0800 // resize this texture when warpimagesize changes
|
||||
#define TEXPREF_PREMULTIPLY 0x1000 // rgb = rgb*a; a=a;
|
||||
|
||||
enum srcformat {SRC_INDEXED, SRC_LIGHTMAP, SRC_RGBA, SRC_EXTERNAL};
|
||||
enum srcformat {SRC_INDEXED, SRC_LIGHTMAP, SRC_RGBA, SRC_EXTERNAL, SRC_FIRSTCOMPRESSED};
|
||||
extern qboolean gl_texture_s3tc, gl_texture_rgtc, gl_texture_bptc, gl_texture_etc2, gl_texture_astc;
|
||||
|
||||
typedef uintptr_t src_offset_t;
|
||||
|
||||
|
@ -87,6 +88,9 @@ void TexMgr_FreeTexturesForOwner (qmodel_t *owner);
|
|||
void TexMgr_NewGame (void);
|
||||
void TexMgr_Init (void);
|
||||
void TexMgr_DeleteTextureObjects (void);
|
||||
enum srcformat TexMgr_FormatForCode (const char *code); //returns SRC_EXTERNAL when not known.
|
||||
size_t TexMgr_ImageSize (int width, int height, enum srcformat format);
|
||||
void TexMgr_BlockSize (enum srcformat format, int *bytes, int *width, int *height);
|
||||
|
||||
// IMAGE LOADING
|
||||
gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int height, enum srcformat format,
|
||||
|
|
|
@ -68,6 +68,8 @@ static int gl_version_minor;
|
|||
static const char *gl_extensions;
|
||||
static char * gl_extensions_nice;
|
||||
|
||||
qboolean gl_texture_s3tc, gl_texture_rgtc, gl_texture_bptc, gl_texture_etc2, gl_texture_astc;
|
||||
|
||||
static vmode_t modelist[MAX_MODE_LIST];
|
||||
static int nummodes;
|
||||
|
||||
|
@ -1172,6 +1174,12 @@ static void GL_CheckExtensions (void)
|
|||
{
|
||||
Con_Warning ("texture_non_power_of_two not supported\n");
|
||||
}
|
||||
|
||||
gl_texture_s3tc = ( GL_ParseExtensionList(gl_extensions, "GL_EXT_texture_compression_s3tc"));
|
||||
gl_texture_rgtc = (gl_version_major >= 3 || GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_compression_rgtc"));
|
||||
gl_texture_bptc = (gl_version_major > 4 || (gl_version_major == 4 && gl_version_minor >= 2) || GL_ParseExtensionList(gl_extensions, "GL_ARB_texture_compression_bptc"));
|
||||
gl_texture_etc2 = (gl_version_major > 4 || (gl_version_major == 4 && gl_version_minor >= 3) || GL_ParseExtensionList(gl_extensions, "GL_ARB_ES3_compatibility"));
|
||||
gl_texture_astc = (gl_version_major > 4 || (gl_version_major == 4 && gl_version_minor >= 3) || GL_ParseExtensionList(gl_extensions, "GL_ARB_ES3_2_compatibility") || GL_ParseExtensionList(gl_extensions, "GL_KHR_texture_compression_astc_ldr"));
|
||||
|
||||
// GLSL
|
||||
//
|
||||
|
|
|
@ -433,7 +433,7 @@ void GL_MakeAliasModelDisplayLists (qmodel_t *m, aliashdr_t *hdr);
|
|||
void Sky_Init (void);
|
||||
void Sky_DrawSky (void);
|
||||
void Sky_NewMap (void);
|
||||
void Sky_LoadTexture (texture_t *mt);
|
||||
void Sky_LoadTexture (texture_t *mt, enum srcformat fmt, unsigned int width, unsigned int height);
|
||||
void Sky_LoadSkyBox (const char *name);
|
||||
extern qboolean skyroom_drawn; //we draw a skyroom this frame
|
||||
extern qboolean skyroom_enabled; //we know where the skyroom is ...
|
||||
|
|
Loading…
Reference in a new issue