1
0
forked from 0ad/0ad

Support reading DDS files with mipmaps

This was SVN commit r2273.
This commit is contained in:
Ykkrosh 2005-05-10 18:29:18 +00:00
parent bc5122fa08
commit 1436e919c1
3 changed files with 115 additions and 23 deletions

View File

@ -363,7 +363,7 @@ int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
// convenient local copies. note: have been validated by CHECK_TEX.
GLsizei w = (GLsizei)t->ti.w;
GLsizei h = (GLsizei)t->ti.h;
u32 bpp = t->ti.bpp; // used for S3TC size calc
u32 bpp = t->ti.bpp; // used for S3TC/mipmap size calc
GLenum fmt = t->fmt;
GLint filter = t->filter;
GLenum int_fmt = t->int_fmt;
@ -385,40 +385,127 @@ int tex_upload(const Handle ht, int filter_ovr, int int_fmt_ovr, int fmt_ovr)
// magnify can only be linear or nearest
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
// activate automatic mipmap generation if called for and possible.
if(need_mipmaps)
/*
There are various combinations of desires/abilities, relating to how
(and whether) mipmaps should be generated. Currently there are only
4^2 such combinations:
/mipmaps available in texture
#######
/mipmaps needed
#######
.---+---+---+---.
| Au| Mu| Nu| Nu|#-auto mipmap generation available
|---+---+---+---|#
| Ac| Mc| Nc| Nc|# #-texture is compressed
|---+---+---+---|# #
| X | Mc| Nc| Nc| #
|---+---+---+---| #
| G | Mu| Nu| Nu|
`---+---+---+---'
Au = auto_mipmap_gen, then 'Nu'
Ac = auto_mipmap_gen, then 'Nc'
X = failure; just fall back to GL_LINEAR and 'Nc'
G = gluBuild2DMipmaps
Mu = glTexImage2D, mipmap levels
Mc = glCompressedTexImage2DARB, mipmap levels
Nu = glTexImage2D
Nc = glCompressedTexImage2DARB
if (Au || Ac)
enable automatic mipmap generation
switch to 'N*'
if (X)
set GL_LINEAR
switch to 'Nc'
if (G)
gluBuild2DMipmaps
if (Nu)
glTexImage2D
if (Nc)
glCompressedTexImage2DARB
if (Mu)
for each mipmap level
glTexImage2D
if (Mc)
for each mipmap level
glCompressedTexImage2DARB
*/
bool is_compressed = fmt_is_s3tc(fmt);
bool has_mipmaps = (t->ti.flags & TEX_MIPMAPS ? true : false);
enum { Au, Ac, Mu, Mc, Nu, Nc, X, G };
int states[4][4] = {
{ Au, Mu, Nu, Nu },
{ Ac, Mc, Nc, Nc },
{ X, Mc, Nc, Nc },
{ G, Mu, Nu, Nu }
};
int state = states[auto_mipmap_gen ? (is_compressed ? 1 : 0) : (is_compressed ? 2 : 3)] // row
[need_mipmaps ? (has_mipmaps ? 1 : 0) : (has_mipmaps ? 2 : 3)]; // column
if(state == Au || state == Ac)
{
// it's supported; activate. this works for S3TC as well.
if(auto_mipmap_gen != GL_FALSE)
glTexParameteri(GL_TEXTURE_2D, auto_mipmap_gen, GL_TRUE);
// auto generation not supported and gluBuild2DMipmaps doesn't
// work for precompressed textures => no easy way to generate
// mipmaps. revert to a filter that doesn't require them.
else if(fmt_is_s3tc(fmt))
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, auto_mipmap_gen, GL_TRUE);
state = (state == Au ? Nu : Nc);
}
// pre-compressed (S3TC) texture
if(fmt_is_s3tc(fmt))
if(state == X)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
state = Nc;
}
if(state == G)
gluBuild2DMipmaps(GL_TEXTURE_2D, int_fmt, w, h, fmt, GL_UNSIGNED_BYTE, tex_data);
else
if(state == Nu)
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE, tex_data);
else
if(state == Nc)
{
const GLsizei tex_size = w * h * bpp / 8;
glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, fmt, w, h, 0, tex_size, tex_data);
}
// uncompressed texture
else
if(state == Mu || state == Mc)
{
// manual mipmap gen via GLU (box filter)
if(need_mipmaps && !auto_mipmap_gen)
gluBuild2DMipmaps(GL_TEXTURE_2D, int_fmt, w, h, fmt, GL_UNSIGNED_BYTE, tex_data);
// auto mipmap gen, or don't need mipmaps
else
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE, tex_data);
int level = 0;
GLsizei level_w = w;
GLsizei level_h = h;
char* mipmap_data = (char*)tex_data;
while (level_w && level_h)
{
GLsizei tex_size;
if (state == Mu)
{
tex_size = w * h * bpp;
glTexImage2D(GL_TEXTURE_2D, level, int_fmt, level_w?level_w:1, level_h?level_h:1, 0, fmt, GL_UNSIGNED_BYTE, mipmap_data);
}
else
{
// Round up to an integer number of 4x4 blocks
tex_size = std::max(1, level_w/4) * std::max(1, level_h/4) * 16 * bpp/8;
glCompressedTexImage2DARB(GL_TEXTURE_2D, level, fmt, level_w?level_w:1, level_h?level_h:1, 0, tex_size, mipmap_data);
}
mipmap_data += tex_size;
level++;
level_w /= 2;
level_h /= 2;
}
}
else
debug_warn("Invalid state in tex_upload");
mem_free_h(t->ti.hm);
t->has_been_uploaded = true;
oglCheck();
return 0;
}

View File

@ -460,14 +460,15 @@ fail:
break;
}
if(mipmaps)
flags |= TEX_MIPMAPS;
// if(file_size != hdr_size + img_size)
// err = "file size mismatch";
if(w % 4 || h % 4)
err = "image dimensions not padded to S3TC block size";
if(!w || !h)
err = "width or height = 0";
// if(mipmaps > 0) // (PT: Not an error, since we probably want
// err = "contains mipmaps"; // to support mipmapped textures eventually)
if(bpp == 0)
err = "invalid pixel format (not DXT{1,3,5})";
if((sd_flags & sd_req_flags) != sd_req_flags)

View File

@ -35,7 +35,11 @@ enum TexInfoFlags
// to indicate the image orientation, or to tex_set_global_orientation.
TEX_BOTTOM_UP = 0x40,
TEX_TOP_DOWN = 0x80,
TEX_ORIENTATION = TEX_BOTTOM_UP|TEX_TOP_DOWN // mask
TEX_ORIENTATION = TEX_BOTTOM_UP|TEX_TOP_DOWN, // mask
// mipmaps - if this flag is set, the image contains data for all
// mipmap levels down to 1x1, stored contiguously.
TEX_MIPMAPS = 0x100
};
// minimize size - stored in ogl tex resource control block