GLTEXTURETYPE_2D,
GLTEXTURETYPE_3D,
GLTEXTURETYPE_CUBEMAP,
- GLTEXTURETYPE_RECTANGLE,
GLTEXTURETYPE_TOTAL
}
gltexturetype_t;
-static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_RECTANGLE_ARB};
-static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2, 2};
+static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB};
+static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2};
static int cubemapside[6] =
{
GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
// d3d stuff the backend needs
void *d3dtexture;
#ifdef SUPPORTD3D
+ qboolean d3disdepthsurface; // for depth/stencil surfaces
int d3dformat;
int d3dusage;
int d3dpool;
else
Host_Error("R_FreeTexture: texture \"%s\" not linked in pool", glt->identifier);
- if (glt->texnum)
+ switch(vid.renderpath)
{
- CHECKGLERROR
- qglDeleteTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ if (glt->texnum)
+ {
+ CHECKGLERROR
+ qglDeleteTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
+ }
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ if (glt->d3disdepthsurface)
+ IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dtexture);
+ else if (glt->tiledepth > 1)
+ IDirect3DVolumeTexture9_Release((IDirect3DVolumeTexture9 *)glt->d3dtexture);
+ else if (glt->sides == 6)
+ IDirect3DCubeTexture9_Release((IDirect3DCubeTexture9 *)glt->d3dtexture);
+ else
+ IDirect3DTexture9_Release((IDirect3DTexture9 *)glt->d3dtexture);
+ glt->d3dtexture = NULL;
+#endif
+ break;
+ case RENDERPATH_D3D10:
+ Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
+ case RENDERPATH_D3D11:
+ Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
}
if (glt->inputtexels)
for (glt = pool->gltchain;glt;glt = glt->chain)
{
// only update already uploaded images
- if (glt->d3dtexture && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
+ if (glt->d3dtexture && !glt->d3disdepthsurface && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
{
if (glt->flags & TEXF_MIPMAP)
{
break;
}
- if (outwidth)
+ if (vid.support.arb_texture_non_power_of_two)
{
- if (vid.support.arb_texture_non_power_of_two)
- width2 = min(inwidth >> picmip, maxsize);
- else
- {
- for (width2 = 1;width2 < inwidth;width2 <<= 1);
- for (width2 >>= picmip;width2 > maxsize;width2 >>= 1);
- }
- *outwidth = max(1, width2);
+ width2 = min(inwidth >> picmip, maxsize);
+ height2 = min(inheight >> picmip, maxsize);
+ depth2 = min(indepth >> picmip, maxsize);
}
- if (outheight)
+ else
{
- if (vid.support.arb_texture_non_power_of_two)
- height2 = min(inheight >> picmip, maxsize);
- else
- {
- for (height2 = 1;height2 < inheight;height2 <<= 1);
- for (height2 >>= picmip;height2 > maxsize;height2 >>= 1);
- }
- *outheight = max(1, height2);
+ for (width2 = 1;width2 < inwidth;width2 <<= 1);
+ for (width2 >>= picmip;width2 > maxsize;width2 >>= 1);
+ for (height2 = 1;height2 < inheight;height2 <<= 1);
+ for (height2 >>= picmip;height2 > maxsize;height2 >>= 1);
+ for (depth2 = 1;depth2 < indepth;depth2 <<= 1);
+ for (depth2 >>= picmip;depth2 > maxsize;depth2 >>= 1);
}
- if (outdepth)
+
+ switch(vid.renderpath)
{
- if (vid.support.arb_texture_non_power_of_two)
- depth2 = min(indepth >> picmip, maxsize);
- else
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_CGGL:
+ case RENDERPATH_D3D10:
+ case RENDERPATH_D3D11:
+ break;
+ case RENDERPATH_D3D9:
+#if 0
+ // for some reason the REF rasterizer (and hence the PIX debugger) does not like small textures...
+ if (texturetype == GLTEXTURETYPE_2D)
{
- for (depth2 = 1;depth2 < indepth;depth2 <<= 1);
- for (depth2 >>= picmip;depth2 > maxsize;depth2 >>= 1);
+ width2 = max(width2, 2);
+ height2 = max(height2, 2);
}
- *outdepth = max(1, depth2);
+#endif
+ break;
}
miplevels = 1;
while(extent >>= 1)
miplevels++;
}
+
+ if (outwidth)
+ *outwidth = max(1, width2);
+ if (outheight)
+ *outheight = max(1, height2);
+ if (outdepth)
+ *outdepth = max(1, depth2);
if (outmiplevels)
*outmiplevels = miplevels;
}
break;
case RENDERPATH_D3D9:
#ifdef SUPPORTD3D
- if (glt->tiledepth > 1)
+ if (glt->d3disdepthsurface)
+ IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dtexture);
+ else if (glt->tiledepth > 1)
IDirect3DVolumeTexture9_Release((IDirect3DVolumeTexture9 *)glt->d3dtexture);
else if (glt->sides == 6)
IDirect3DCubeTexture9_Release((IDirect3DCubeTexture9 *)glt->d3dtexture);
#ifdef SUPPORTD3D
{
HRESULT d3dresult;
- if (glt->tiledepth > 1)
+ if (glt->d3disdepthsurface)
+ {
+ if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dtexture, NULL)))
+ Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
+ }
+ else if (glt->tiledepth > 1)
{
if (FAILED(d3dresult = IDirect3DDevice9_CreateVolumeTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->tiledepth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DVolumeTexture9 **)&glt->d3dtexture, NULL)))
Sys_Error("IDirect3DDevice9_CreateVolumeTexture failed!");
prevbuffer = colorconvertbuffer;
}
+ if (glt->flags & TEXF_RGBMULTIPLYBYALPHA)
+ {
+ // multiply RGB channels by A channel before uploading
+ int alpha;
+ for (i = 0;i < width*height*depth*4;i += 4)
+ {
+ alpha = prevbuffer[i+3];
+ colorconvertbuffer[i] = (prevbuffer[i] * alpha) >> 8;
+ colorconvertbuffer[i+1] = (prevbuffer[i+1] * alpha) >> 8;
+ colorconvertbuffer[i+2] = (prevbuffer[i+2] * alpha) >> 8;
+ colorconvertbuffer[i+3] = alpha;
+ }
+ prevbuffer = colorconvertbuffer;
+ }
+
// scale up to a power of 2 size (if appropriate)
if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
{
}
}
break;
- case GLTEXTURETYPE_RECTANGLE:
- qglTexImage2D(GL_TEXTURE_RECTANGLE_ARB, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, NULL);CHECKGLERROR
- break;
}
GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
}
}
break;
- case GLTEXTURETYPE_RECTANGLE:
- Sys_Error("Direct3D does not have RECTANGLE textures\n");
- break;
}
}
glt->d3daddressw = 0;
if (cls.state == ca_dedicated)
return NULL;
- if (texturetype == GLTEXTURETYPE_RECTANGLE && !vid.support.arb_texture_rectangle)
- {
- Con_Printf ("R_LoadTexture: rectangle texture not supported by driver\n");
- return NULL;
- }
if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map)
{
Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n");
glt->d3dformat = d3dformat;
glt->d3dusage = d3dusage;
glt->d3dpool = d3dpool;
- if (glt->tiledepth > 1)
+ glt->d3disdepthsurface = textype == TEXTYPE_SHADOWMAP;
+ if (glt->d3disdepthsurface)
+ {
+ if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dtexture, NULL)))
+ Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
+ }
+ else if (glt->tiledepth > 1)
{
if (FAILED(d3dresult = IDirect3DDevice9_CreateVolumeTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->tiledepth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DVolumeTexture9 **)&glt->d3dtexture, NULL)))
Sys_Error("IDirect3DDevice9_CreateVolumeTexture failed!");
return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, miplevel, textype, GLTEXTURETYPE_CUBEMAP, data, palette);
}
-rtexture_t *R_LoadTextureRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
-{
- return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, miplevel, textype, GLTEXTURETYPE_RECTANGLE, data, palette);
-}
-
static int R_ShadowMapTextureFlags(int precision, qboolean filter)
{
int flags = TEXF_RENDERTARGET | TEXF_CLAMP;
return flags;
}
-rtexture_t *R_LoadTextureShadowMapRectangle(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter)
-{
- return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), -1, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_RECTANGLE, NULL, NULL);
-}
-
rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter)
{
return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), -1, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL);
}
-rtexture_t *R_LoadTextureShadowMapCube(rtexturepool_t *rtexturepool, const char *identifier, int width, int precision, qboolean filter)
-{
- return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, R_ShadowMapTextureFlags(precision, filter), -1, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_CUBEMAP, NULL, NULL);
-}
-
int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha)
{
gltexture_t *glt = (gltexture_t *)rt;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: ddsfourcc = "DXT3";bytesperblock = 16;break;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: ddsfourcc = "DXT5";bytesperblock = 16;break;
}
+ // if premultiplied alpha, say so in the DDS file
+ if(glt->flags & TEXF_RGBMULTIPLYBYALPHA)
+ {
+ switch(internalformat)
+ {
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: ddsfourcc = "DXT2";break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: ddsfourcc = "DXT4";break;
+ }
+ }
if (!bytesperblock && skipuncompressed)
return -3; // skipped
memset(mipinfo, 0, sizeof(mipinfo));
}
}
}
- else if (!memcmp(dds+84, "DXT3", 4))
+ else if (!memcmp(dds+84, "DXT3", 4) || !memcmp(dds+84, "DXT2", 4))
{
+ if(!memcmp(dds+84, "DXT2", 4))
+ {
+ if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
+ {
+ Con_Printf("^1%s: expecting DXT3 image without premultiplied alpha, got DXT2 image with premultiplied alpha\n", filename);
+ }
+ }
+ else
+ {
+ if(flags & TEXF_RGBMULTIPLYBYALPHA)
+ {
+ Con_Printf("^1%s: expecting DXT2 image without premultiplied alpha, got DXT3 image without premultiplied alpha\n", filename);
+ }
+ }
if(!vid.support.ext_texture_compression_s3tc)
{
Mem_Free(dds);
}
// we currently always assume alpha
}
- else if (!memcmp(dds+84, "DXT5", 4))
+ else if (!memcmp(dds+84, "DXT5", 4) || !memcmp(dds+84, "DXT4", 4))
{
+ if(!memcmp(dds+84, "DXT4", 4))
+ {
+ if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
+ {
+ Con_Printf("^1%s: expecting DXT5 image without premultiplied alpha, got DXT4 image with premultiplied alpha\n", filename);
+ }
+ }
+ else
+ {
+ if(flags & TEXF_RGBMULTIPLYBYALPHA)
+ {
+ Con_Printf("^1%s: expecting DXT4 image without premultiplied alpha, got DXT5 image without premultiplied alpha\n", filename);
+ }
+ }
if(!vid.support.ext_texture_compression_s3tc)
{
Mem_Free(dds);