X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_textures.c;h=ded21684571cd6f05907751f46da198807d91a11;hp=37c135edc45807fd14b62908a691e65ae55fe7c4;hb=263c1c74882c45b9d17ddd6ff5ca80a5f8db777c;hpb=9615163fe2a5dfa13ef832d0d0e10b9cda619840 diff --git a/gl_textures.c b/gl_textures.c index 37c135ed..ded21684 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -38,7 +38,7 @@ cvar_t gl_texturecompression_reflectmask = {CVAR_SAVE, "gl_texturecompression_re cvar_t gl_texturecompression_sprites = {CVAR_SAVE, "gl_texturecompression_sprites", "1", "whether to compress sprites"}; cvar_t gl_nopartialtextureupdates = {CVAR_SAVE, "gl_nopartialtextureupdates", "0", "use alternate path for dynamic lightmap updates that avoids a possibly slow code path in the driver"}; cvar_t r_texture_dds_load_alphamode = {0, "r_texture_dds_load_alphamode", "1", "0: trust DDPF_ALPHAPIXELS flag, 1: texture format and brute force search if ambiguous, 2: texture format only"}; -cvar_t r_texture_dds_load_logfailure = {0, "r_texture_dds_load_logfailure", "0", "log missing DDS textures to ddstexturefailures.log"}; +cvar_t r_texture_dds_load_logfailure = {0, "r_texture_dds_load_logfailure", "0", "log missing DDS textures to ddstexturefailures.log, 0: done log, 1: log with no optional textures (_norm, glow etc.). 2: log all"}; cvar_t r_texture_dds_swdecode = {0, "r_texture_dds_swdecode", "0", "0: don't software decode DDS, 1: software decode DDS if unsupported, 2: always software decode DDS"}; qboolean gl_filter_force = false; @@ -81,6 +81,11 @@ typedef struct textypeinfo_s textypeinfo_t; #ifdef USE_GLES2 + +// we use these internally even if we never deliver such data to the driver +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 + // framebuffer texture formats // GLES2 devices rarely support depth textures, so we actually use a renderbuffer there static textypeinfo_t textype_shadowmap16_comp = {"shadowmap16_comp", TEXTYPE_SHADOWMAP16_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; @@ -102,6 +107,9 @@ static textypeinfo_t textype_rgba = {"rgba", static textypeinfo_t textype_rgba_alpha = {"rgba_alpha", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE }; static textypeinfo_t textype_bgra = {"bgra", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE }; static textypeinfo_t textype_bgra_alpha = {"bgra_alpha", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE }; +#ifdef __ANDROID__ +static textypeinfo_t textype_etc1 = {"etc1", TEXTYPE_ETC1 , 1, 3, 0.5f, GL_ETC1_RGB8_OES , 0 , 0 }; +#endif #else // framebuffer texture formats static textypeinfo_t textype_shadowmap16_comp = {"shadowmap16_comp", TEXTYPE_SHADOWMAP16_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; @@ -157,7 +165,9 @@ typedef enum gltexturetype_e gltexturetype_t; static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP}; +#ifdef GL_TEXTURE_WRAP_R static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2}; +#endif static int cubemapside[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, @@ -175,6 +185,7 @@ typedef struct gltexture_s int texnum; // GL texture slot number int renderbuffernum; // GL renderbuffer slot number qboolean dirty; // indicates that R_RealGetTexture should be called + qboolean glisdepthstencil; // indicates that FBO attachment has to be GL_DEPTH_STENCIL_ATTACHMENT int gltexturetypeenum; // used by R_Mesh_TexBind // d3d stuff the backend needs void *d3dtexture; @@ -267,6 +278,25 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags) { switch(textype) { +#ifdef USE_GLES2 + case TEXTYPE_PALETTE: return (flags & TEXF_ALPHA) ? &textype_palette_alpha : &textype_palette; + case TEXTYPE_RGBA: return ((flags & TEXF_ALPHA) ? &textype_rgba_alpha : &textype_rgba); + case TEXTYPE_BGRA: return ((flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra); +#ifdef __ANDROID__ + case TEXTYPE_ETC1: return &textype_etc1; +#endif + case TEXTYPE_ALPHA: return &textype_alpha; + case TEXTYPE_COLORBUFFER: return &textype_colorbuffer; + case TEXTYPE_COLORBUFFER16F: return &textype_colorbuffer16f; + case TEXTYPE_COLORBUFFER32F: return &textype_colorbuffer32f; + case TEXTYPE_DEPTHBUFFER16: return &textype_depth16; + case TEXTYPE_DEPTHBUFFER24: return &textype_depth24; + case TEXTYPE_DEPTHBUFFER24STENCIL8: return &textype_depth24stencil8; + case TEXTYPE_SHADOWMAP16_COMP: return &textype_shadowmap16_comp; + case TEXTYPE_SHADOWMAP16_RAW: return &textype_shadowmap16_raw; + case TEXTYPE_SHADOWMAP24_COMP: return &textype_shadowmap24_comp; + case TEXTYPE_SHADOWMAP24_RAW: return &textype_shadowmap24_raw; +#else case TEXTYPE_DXT1: return &textype_dxt1; case TEXTYPE_DXT1A: return &textype_dxt1a; case TEXTYPE_DXT3: return &textype_dxt3; @@ -292,6 +322,7 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags) case TEXTYPE_SRGB_PALETTE: return (flags & TEXF_ALPHA) ? &textype_sRGB_palette_alpha : &textype_sRGB_palette; case TEXTYPE_SRGB_RGBA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_sRGB_rgba_alpha_compress : &textype_sRGB_rgba_compress) : ((flags & TEXF_ALPHA) ? &textype_sRGB_rgba_alpha : &textype_sRGB_rgba); case TEXTYPE_SRGB_BGRA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_sRGB_bgra_alpha_compress : &textype_sRGB_bgra_compress) : ((flags & TEXF_ALPHA) ? &textype_sRGB_bgra_alpha : &textype_sRGB_bgra); +#endif default: Host_Error("R_GetTexTypeInfo: unknown texture format"); break; @@ -370,7 +401,7 @@ void R_FreeTexture(rtexture_t *rt) if (glt->renderbuffernum) { CHECKGLERROR - qglDeleteRenderbuffersEXT(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR + qglDeleteRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR } break; case RENDERPATH_D3D9: @@ -824,7 +855,7 @@ static void r_textures_devicelost(void) { int i, endindex; gltexture_t *glt; - endindex = Mem_ExpandableArray_IndexRange(&texturearray); + endindex = (int)Mem_ExpandableArray_IndexRange(&texturearray); for (i = 0;i < endindex;i++) { glt = (gltexture_t *) Mem_ExpandableArray_RecordAtIndex(&texturearray, i); @@ -868,7 +899,7 @@ static void r_textures_devicerestored(void) { int i, endindex; gltexture_t *glt; - endindex = Mem_ExpandableArray_IndexRange(&texturearray); + endindex = (int)Mem_ExpandableArray_IndexRange(&texturearray); for (i = 0;i < endindex;i++) { glt = (gltexture_t *) Mem_ExpandableArray_RecordAtIndex(&texturearray, i); @@ -963,7 +994,9 @@ void R_Textures_Init (void) void R_Textures_Frame (void) { +#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT static int old_aniso = 0; +#endif // could do procedural texture animation here, if we keep track of which // textures were accessed this frame... @@ -981,6 +1014,7 @@ void R_Textures_Frame (void) colorconvertbuffer = NULL; } +#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT if (old_aniso != gl_texture_anisotropy.integer) { gltexture_t *glt; @@ -1024,6 +1058,7 @@ void R_Textures_Frame (void) break; } } +#endif } static void R_MakeResizeBufferBigger(int size) @@ -1049,6 +1084,7 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet CHECKGLERROR +#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT if (vid.support.ext_texture_filter_anisotropic && (flags & TEXF_MIPMAP)) { int aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy); @@ -1056,6 +1092,7 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet Cvar_SetValueQuick(&gl_texture_anisotropy, aniso); qglTexParameteri(textureenum, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);CHECKGLERROR } +#endif qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode);CHECKGLERROR qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode);CHECKGLERROR #ifdef GL_TEXTURE_WRAP_R @@ -1110,6 +1147,7 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR } +#ifdef GL_TEXTURE_COMPARE_MODE_ARB switch(textype) { case TEXTYPE_SHADOWMAP16_COMP: @@ -1127,6 +1165,7 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet default: break; } +#endif CHECKGLERROR } @@ -1280,6 +1319,7 @@ static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data) oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]); qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR +#ifndef USE_GLES2 #ifdef GL_TEXTURE_COMPRESSION_HINT_ARB if (qglGetCompressedTexImageARB) { @@ -1289,6 +1329,7 @@ static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data) qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_FASTEST); CHECKGLERROR } +#endif #endif switch(glt->texturetype) { @@ -1623,7 +1664,7 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden case TEXTYPE_SRGB_DXT1A: textype = TEXTYPE_DXT1A ;convertsRGB = true;break; case TEXTYPE_SRGB_DXT3: textype = TEXTYPE_DXT3 ;convertsRGB = true;break; case TEXTYPE_SRGB_DXT5: textype = TEXTYPE_DXT5 ;convertsRGB = true;break; - case TEXTYPE_SRGB_PALETTE: textype = TEXTYPE_PALETTE;convertsRGB = true;break; + case TEXTYPE_SRGB_PALETTE: textype = TEXTYPE_PALETTE;/*convertsRGB = true;*/break; case TEXTYPE_SRGB_RGBA: textype = TEXTYPE_RGBA ;convertsRGB = true;break; case TEXTYPE_SRGB_BGRA: textype = TEXTYPE_BGRA ;convertsRGB = true;break; default: @@ -1758,6 +1799,7 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1; glt->texnum = 0; glt->dirty = false; + glt->glisdepthstencil = false; glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype]; // init the dynamic texture attributes, too [11/22/2007 Black] glt->updatecallback = NULL; @@ -1929,7 +1971,8 @@ rtexture_t *R_LoadTextureRenderBuffer(rtexturepool_t *rtexturepool, const char * glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1; glt->texnum = 0; glt->dirty = false; - glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype]; + glt->glisdepthstencil = textype == TEXTYPE_DEPTHBUFFER24STENCIL8; + glt->gltexturetypeenum = GL_TEXTURE_2D; // init the dynamic texture attributes, too [11/22/2007 Black] glt->updatecallback = NULL; glt->updatacallback_data = NULL; @@ -1946,11 +1989,11 @@ rtexture_t *R_LoadTextureRenderBuffer(rtexturepool_t *rtexturepool, const char * case RENDERPATH_GLES1: case RENDERPATH_GLES2: CHECKGLERROR - qglGenRenderbuffersEXT(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR - qglBindRenderbufferEXT(GL_RENDERBUFFER, glt->renderbuffernum);CHECKGLERROR - qglRenderbufferStorageEXT(GL_RENDERBUFFER, glt->glinternalformat, glt->tilewidth, glt->tileheight);CHECKGLERROR + qglGenRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR + qglBindRenderbuffer(GL_RENDERBUFFER, glt->renderbuffernum);CHECKGLERROR + qglRenderbufferStorage(GL_RENDERBUFFER, glt->glinternalformat, glt->tilewidth, glt->tileheight);CHECKGLERROR // note we can query the renderbuffer for info with glGetRenderbufferParameteriv for GL_WIDTH, GL_HEIGHt, GL_RED_SIZE, GL_GREEN_SIZE, GL_BLUE_SIZE, GL_GL_ALPHA_SIZE, GL_DEPTH_SIZE, GL_STENCIL_SIZE, GL_INTERNAL_FORMAT - qglBindRenderbufferEXT(GL_RENDERBUFFER, 0);CHECKGLERROR + qglBindRenderbuffer(GL_RENDERBUFFER, 0);CHECKGLERROR break; case RENDERPATH_D3D9: #ifdef SUPPORTD3D @@ -2066,7 +2109,7 @@ int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipunco mipinfo[0][0] = glt->tilewidth; mipinfo[0][1] = glt->tileheight; mipmaps = 1; - if ((glt->flags & TEXF_MIPMAP) && !(glt->tilewidth == 1 && glt->tilewidth == 1)) + if ((glt->flags & TEXF_MIPMAP) && !(glt->tilewidth == 1 && glt->tileheight == 1)) { for (mip = 1;mip < 16;mip++) { @@ -2145,7 +2188,12 @@ int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipunco #endif } -rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel) // DDS textures are opaque, so miplevel isn't a pointer but just seen as a hint +#ifdef __ANDROID__ +// ELUAN: FIXME: separate this code +#include "ktx10/include/ktx.h" +#endif + +rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel, qboolean optionaltexture) // DDS textures are opaque, so miplevel isn't a pointer but just seen as a hint { int i, size, dds_format_flags, dds_miplevels, dds_width, dds_height; //int dds_flags; @@ -2164,17 +2212,161 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen unsigned char *dds; fs_offset_t ddsfilesize; unsigned int ddssize; - qboolean force_swdecode = (r_texture_dds_swdecode.integer > 1); + qboolean force_swdecode, npothack; +#ifdef __ANDROID__ + // ELUAN: FIXME: separate this code + char vabuf[1024]; + char vabuf2[1024]; + int strsize; + KTX_dimensions sizes; +#endif if (cls.state == ca_dedicated) return NULL; +#ifdef __ANDROID__ + // ELUAN: FIXME: separate this code + if (vid.renderpath != RENDERPATH_GLES2) + { + Con_DPrintf("KTX texture format is only supported on the GLES2 renderpath\n"); + return NULL; + } + + // some textures are specified with extensions, so it becomes .tga.dds + FS_StripExtension (filename, vabuf2, sizeof(vabuf2)); + FS_StripExtension (vabuf2, vabuf, sizeof(vabuf)); + FS_DefaultExtension (vabuf, ".ktx", sizeof(vabuf)); + strsize = strlen(vabuf); + if (strsize > 5) + for (i = 0; i <= strsize - 4; i++) // copy null termination + vabuf[i] = vabuf[i + 4]; + + Con_DPrintf("Loading %s...\n", vabuf); + dds = FS_LoadFile(vabuf, tempmempool, true, &ddsfilesize); + ddssize = ddsfilesize; + + if (!dds) + { + Con_DPrintf("Not found!\n"); + return NULL; // not found + } + Con_DPrintf("Found!\n"); + + if (flags & TEXF_ALPHA) + { + Con_DPrintf("KTX texture with alpha not supported yet, disabling\n"); + flags &= ~TEXF_ALPHA; + } + + { + GLenum target; + GLenum glerror; + GLboolean isMipmapped; + KTX_error_code ktxerror; + + glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray); + + // texture uploading can take a while, so make sure we're sending keepalives + CL_KeepaliveMessage(false); + + // create the texture object + CHECKGLERROR + GL_ActiveTexture(0); + oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[GLTEXTURETYPE_2D]); + qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR + qglBindTexture(gltexturetypeenums[GLTEXTURETYPE_2D], glt->texnum);CHECKGLERROR + + // upload the texture + // we need to restore the texture binding after finishing the upload + + // NOTE: some drivers fail with ETC1 NPOT (only PowerVR?). This may make the driver crash later. + ktxerror = ktxLoadTextureM(dds, ddssize, &glt->texnum, &target, &sizes, &isMipmapped, &glerror, + 0, NULL);// can't CHECKGLERROR, the lib catches it + + // FIXME: delete texture if we fail here + if (target != GL_TEXTURE_2D) + { + qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR + Mem_Free(dds); + Con_DPrintf("%s target != GL_TEXTURE_2D, target == %x\n", vabuf, target); + return NULL; // FIXME: delete the texture from memory + } + + if (KTX_SUCCESS == ktxerror) + { + textype = TEXTYPE_ETC1; + flags &= ~TEXF_COMPRESS; // don't let the textype be wrong + + // return whether this texture is transparent + if (hasalphaflag) + *hasalphaflag = (flags & TEXF_ALPHA) != 0; + + // TODO: apply gl_picmip + // TODO: avgcolor + // TODO: srgb + // TODO: only load mipmaps if requested + + if (isMipmapped) + flags |= TEXF_MIPMAP; + else + flags &= ~TEXF_MIPMAP; + + texinfo = R_GetTexTypeInfo(textype, flags); + + strlcpy (glt->identifier, vabuf, sizeof(glt->identifier)); + glt->pool = pool; + glt->chain = pool->gltchain; + pool->gltchain = glt; + glt->inputwidth = sizes.width; + glt->inputheight = sizes.height; + glt->inputdepth = 1; + glt->flags = flags; + glt->textype = texinfo; + glt->texturetype = GLTEXTURETYPE_2D; + glt->inputdatasize = ddssize; + glt->glinternalformat = texinfo->glinternalformat; + glt->glformat = texinfo->glformat; + glt->gltype = texinfo->gltype; + glt->bytesperpixel = texinfo->internalbytesperpixel; + glt->sides = 1; + glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype]; + glt->tilewidth = sizes.width; + glt->tileheight = sizes.height; + glt->tiledepth = 1; + glt->miplevels = isMipmapped ? 1 : 0; // FIXME + + // after upload we have to set some parameters... +#ifdef GL_TEXTURE_MAX_LEVEL + /* FIXME + if (dds_miplevels >= 1 && !mipcomplete) + { + // need to set GL_TEXTURE_MAX_LEVEL + qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR + } + */ +#endif + GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype); + + qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR + Mem_Free(dds); + return (rtexture_t *)glt; + } + else + { + qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR + Mem_Free(dds); + Con_DPrintf("KTX texture %s failed to load: %x\n", vabuf, ktxerror); + return NULL; + } + } +#endif // __ANDROID__ + dds = FS_LoadFile(filename, tempmempool, true, &ddsfilesize); ddssize = ddsfilesize; if (!dds) { - if(r_texture_dds_load_logfailure.integer) + if (r_texture_dds_load_logfailure.integer && (r_texture_dds_load_logfailure.integer >= 2 || !optionaltexture)) Log_Printf("ddstexturefailures.log", "%s\n", filename); return NULL; // not found } @@ -2238,9 +2430,9 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen Con_Printf("^1%s: invalid DXT1 DDS image\n", filename); return NULL; } - if(r_texture_dds_load_alphamode.integer && (flags & TEXF_ALPHA)) + if (flags & TEXF_ALPHA) { - if(r_texture_dds_load_alphamode.integer == 1) + if (r_texture_dds_load_alphamode.integer == 1) { // check alpha for (i = 0;i < size;i += bytesperblock) @@ -2257,6 +2449,8 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen else flags &= ~TEXF_ALPHA; } + else if (r_texture_dds_load_alphamode.integer == 0) + textype = TEXTYPE_DXT1A; else { flags &= ~TEXF_ALPHA; @@ -2339,9 +2533,17 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen } force_swdecode = false; + npothack = + (!vid.support.arb_texture_non_power_of_two && + ( + (dds_width & (dds_width - 1)) + || + (dds_height & (dds_height - 1)) + ) + ); if(bytesperblock) { - if(vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc) + if(vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && !npothack) { if(r_texture_dds_swdecode.integer > 1) force_swdecode = true; @@ -2452,7 +2654,7 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen avgcolor[1] += ((c >> 5) & 0x3F) + ((c >> 21) & 0x3F); avgcolor[2] += ((c ) & 0x1F) + ((c >> 16) & 0x1F); if(textype == TEXTYPE_DXT5) - avgcolor[3] += (0.5 * mippixels[i-8] + 0.5 * mippixels[i-7]); + avgcolor[3] += (mippixels[i-8] + (int) mippixels[i-7]) * (0.5f / 255.0f); else if(textype == TEXTYPE_DXT3) avgcolor[3] += ( (mippixels_start[i-8] & 0x0F) @@ -2463,11 +2665,11 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen + (mippixels_start[i-6] >> 4) + (mippixels_start[i-5] & 0x0F) + (mippixels_start[i-5] >> 4) - ) * (0.125f / 15.0f * 255.0f); + ) * (0.125f / 15.0f); else - avgcolor[3] += 255; + avgcolor[3] += 1.0f; } - f = (float)bytesperblock / size; + f = (float)bytesperblock / mipsize; avgcolor[0] *= (0.5f / 31.0f) * f; avgcolor[1] *= (0.5f / 63.0f) * f; avgcolor[2] *= (0.5f / 31.0f) * f; @@ -2482,7 +2684,7 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen avgcolor[2] += mippixels[i]; avgcolor[3] += mippixels[i+3]; } - f = (1.0f / 255.0f) * bytesperpixel / size; + f = (1.0f / 255.0f) * bytesperpixel / mipsize; avgcolor[0] *= f; avgcolor[1] *= f; avgcolor[2] *= f; @@ -2619,6 +2821,12 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen glt->tiledepth = 1; glt->miplevels = dds_miplevels; + if(npothack) + { + for (glt->tilewidth = 1;glt->tilewidth < mipwidth;glt->tilewidth <<= 1); + for (glt->tileheight = 1;glt->tileheight < mipheight;glt->tileheight <<= 1); + } + // texture uploading can take a while, so make sure we're sending keepalives CL_KeepaliveMessage(false); @@ -2673,9 +2881,25 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen for (mip = 0;mip <= dds_miplevels;mip++) // <= to include the not-counted "largest" miplevel { + unsigned char *upload_mippixels = mippixels; + int upload_mipwidth = mipwidth; + int upload_mipheight = mipheight; mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel; if (mippixels + mipsize > mippixels_start + mipsize_total) break; + if(npothack) + { + upload_mipwidth = (glt->tilewidth >> mip); + upload_mipheight = (glt->tileheight >> mip); + if(upload_mipwidth != mipwidth || upload_mipheight != mipheight) + // I _think_ they always mismatch, but I was too lazy + // to properly check, and this test here is really + // harmless + { + upload_mippixels = (unsigned char *) Mem_Alloc(tempmempool, 4 * upload_mipwidth * upload_mipheight); + Image_Resample32(mippixels, mipwidth, mipheight, 1, upload_mippixels, upload_mipwidth, upload_mipheight, 1, r_lerpimages.integer); + } + } switch(vid.renderpath) { case RENDERPATH_GL11: @@ -2685,11 +2909,11 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen case RENDERPATH_GLES2: if (bytesperblock) { - qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, glt->glinternalformat, mipwidth, mipheight, 0, mipsize, mippixels);CHECKGLERROR + qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, mipsize, upload_mippixels);CHECKGLERROR } else { - qglTexImage2D(GL_TEXTURE_2D, mip, glt->glinternalformat, mipwidth, mipheight, 0, glt->glformat, glt->gltype, mippixels);CHECKGLERROR + qglTexImage2D(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, glt->glformat, glt->gltype, upload_mippixels);CHECKGLERROR } break; case RENDERPATH_D3D9: @@ -2698,7 +2922,7 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen D3DLOCKED_RECT d3dlockedrect; if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits) { - memcpy(d3dlockedrect.pBits, mippixels, mipsize); + memcpy(d3dlockedrect.pBits, upload_mippixels, mipsize); IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip); } break; @@ -2715,11 +2939,13 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen if (bytesperblock) Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); else - DPSOFTRAST_Texture_UpdateFull(glt->texnum, mippixels); + DPSOFTRAST_Texture_UpdateFull(glt->texnum, upload_mippixels); // DPSOFTRAST calculates its own mipmaps mip = dds_miplevels; break; } + if(upload_mippixels != mippixels) + Mem_Free(upload_mippixels); mippixels += mipsize; if (mipwidth <= 1 && mipheight <= 1) {