#include "jpeg.h"
#include "image_png.h"
#include "intoverflow.h"
+#include "dpsoftrast.h"
cvar_t gl_max_size = {CVAR_SAVE, "gl_max_size", "2048", "maximum allowed texture size, can be used to reduce video memory usage, limited by hardware capabilities (typically 2048, 4096, or 8192)"};
cvar_t gl_max_lightmapsize = {CVAR_SAVE, "gl_max_lightmapsize", "1024", "maximum allowed texture size for lightmap textures, use larger values to improve rendering speed, as long as there is enough video memory available (setting it too high for the hardware will cause very bad performance)"};
cvar_t gl_texturecompression_reflectmask = {CVAR_SAVE, "gl_texturecompression_reflectmask", "1", "whether to compress reflection cubemap masks (mask of which areas of the texture should reflect the generic shiny cubemap)"};
cvar_t gl_nopartialtextureupdates = {CVAR_SAVE, "gl_nopartialtextureupdates", "1", "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 ambigous, 2: texture format only"};
+cvar_t r_texture_dds_load_logfailure = {0, "r_texture_dds_load_logfailure", "1", "log missing DDS textures to ddstexturefailures.log"};
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;
int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR;
int gl_filter_mag = GL_LINEAR;
+DPSOFTRAST_TEXTURE_FILTER dpsoftrast_filter_mipmap = DPSOFTRAST_TEXTURE_FILTER_LINEAR_MIPMAP_TRIANGLE;
+DPSOFTRAST_TEXTURE_FILTER dpsoftrast_filter_nomipmap = DPSOFTRAST_TEXTURE_FILTER_LINEAR;
#ifdef SUPPORTD3D
int d3d_filter_flatmin = D3DTEXF_LINEAR;
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ if (glt->texnum)
+ DPSOFTRAST_Texture_Free(glt->texnum);
+ break;
}
if (glt->inputtexels)
{
const char *name;
int minification, magnification;
+ DPSOFTRAST_TEXTURE_FILTER dpsoftrastfilter_mipmap, dpsoftrastfilter_nomipmap;
}
glmode_t;
static glmode_t modes[6] =
{
- {"GL_NEAREST", GL_NEAREST, GL_NEAREST},
- {"GL_LINEAR", GL_LINEAR, GL_LINEAR},
- {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
- {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
- {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
- {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
+ {"GL_NEAREST", GL_NEAREST, GL_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST},
+ {"GL_LINEAR", GL_LINEAR, GL_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR},
+ {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_NEAREST},
+ {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_LINEAR},
+ {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_NEAREST},
+ {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_LINEAR}
};
#ifdef SUPPORTD3D
gl_filter_mag = modes[i].magnification;
gl_filter_force = ((Cmd_Argc() > 2) && !strcasecmp(Cmd_Argv(2), "force"));
+ dpsoftrast_filter_mipmap = modes[i].dpsoftrastfilter_mipmap;
+ dpsoftrast_filter_nomipmap = modes[i].dpsoftrastfilter_nomipmap;
+
switch(vid.renderpath)
{
case RENDERPATH_GL11:
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ // change all the existing texture objects
+ for (pool = gltexturepoolchain;pool;pool = pool->next)
+ for (glt = pool->gltchain;glt;glt = glt->chain)
+ if (glt->texnum && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
+ DPSOFTRAST_Texture_Filter(glt->texnum, (glt->flags & TEXF_MIPMAP) ? dpsoftrast_filter_mipmap : dpsoftrast_filter_nomipmap);
+ break;
}
}
case RENDERPATH_CGGL:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
+ case RENDERPATH_SOFT:
break;
case RENDERPATH_D3D9:
#if 0
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ break;
}
texturemempool = Mem_AllocPool("texture management", 0, NULL);
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ break;
}
}
}
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ break;
}
}
}
Cvar_RegisterVariable (&gl_texturecompression_reflectmask);
Cvar_RegisterVariable (&gl_nopartialtextureupdates);
Cvar_RegisterVariable (&r_texture_dds_load_alphamode);
+ Cvar_RegisterVariable (&r_texture_dds_load_logfailure);
Cvar_RegisterVariable (&r_texture_dds_swdecode);
R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown, r_textures_newmap, r_textures_devicelost, r_textures_devicerestored);
case RENDERPATH_D3D9:
case RENDERPATH_D3D10:
case RENDERPATH_D3D11:
+ case RENDERPATH_SOFT:
break;
}
}
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ DPSOFTRAST_Texture_UpdatePartial(glt->texnum, 0, data, fragx, fragy, fragwidth, fragheight);
+ break;
}
}
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ switch(glt->texturetype)
+ {
+ case GLTEXTURETYPE_2D:
+ DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
+ break;
+ case GLTEXTURETYPE_3D:
+ DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
+ break;
+ case GLTEXTURETYPE_CUBEMAP:
+ if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
+ {
+ unsigned char *combinedbuffer = (unsigned char *)Mem_Alloc(tempmempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
+ // convert and upload each side in turn,
+ // from a continuous block of input texels
+ // copy the results into combinedbuffer
+ texturebuffer = (unsigned char *)prevbuffer;
+ for (i = 0;i < 6;i++)
+ {
+ prevbuffer = texturebuffer;
+ texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
+ if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
+ {
+ Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
+ prevbuffer = resizebuffer;
+ }
+ // picmip/max_size
+ while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
+ {
+ Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
+ prevbuffer = resizebuffer;
+ }
+ memcpy(combinedbuffer + i*glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel, prevbuffer, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel);
+ }
+ DPSOFTRAST_Texture_UpdateFull(glt->texnum, combinedbuffer);
+ Mem_Free(combinedbuffer);
+ }
+ else
+ DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
+ break;
+ }
+ if (glt->flags & TEXF_FORCELINEAR)
+ DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
+ else if (glt->flags & TEXF_FORCENEAREST)
+ DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
+ else if (glt->flags & TEXF_MIPMAP)
+ DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
+ else
+ DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
+ break;
}
}
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ {
+ int tflags = 0;
+ switch(textype)
+ {
+ case TEXTYPE_PALETTE: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
+ case TEXTYPE_RGBA: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA8;break;
+ case TEXTYPE_BGRA: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
+ case TEXTYPE_COLORBUFFER: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
+ case TEXTYPE_SHADOWMAP: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
+ case TEXTYPE_ALPHA: tflags = DPSOFTRAST_TEXTURE_FORMAT_ALPHA8;break;
+ default: Sys_Error("R_LoadTexture: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
+ }
+ if (glt->miplevels > 1) tflags |= DPSOFTRAST_TEXTURE_FLAG_MIPMAP;
+ if (flags & TEXF_ALPHA) tflags |= DPSOFTRAST_TEXTURE_FLAG_USEALPHA;
+ if (glt->sides == 6) tflags |= DPSOFTRAST_TEXTURE_FLAG_CUBEMAP;
+ if (glt->flags & TEXF_CLAMP) tflags |= DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;
+ glt->texnum = DPSOFTRAST_Texture_New(tflags, glt->tilewidth, glt->tileheight, glt->tiledepth);
+ }
+ break;
}
R_UploadFullTexture(glt, data);
if (!dds)
{
- Log_Printf("ddstexturefailures.log", "%s\n", filename);
+ if(r_texture_dds_load_logfailure.integer)
+ Log_Printf("ddstexturefailures.log", "%s\n", filename);
return NULL; // not found
}
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ glt->texnum = DPSOFTRAST_Texture_New(((glt->flags & TEXF_CLAMP) ? DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE : 0) | (dds_miplevels > 1 ? DPSOFTRAST_TEXTURE_FLAG_MIPMAP : 0), glt->tilewidth, glt->tileheight, glt->tiledepth);
+ break;
}
// upload the texture
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ if (bytesperblock)
+ Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ else
+ DPSOFTRAST_Texture_UpdateFull(glt->texnum, mippixels);
+ // DPSOFTRAST calculates its own mipmaps
+ mip = dds_miplevels;
+ break;
}
mippixels += mipsize;
if (mipwidth <= 1 && mipheight <= 1)
case RENDERPATH_D3D11:
Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
break;
+ case RENDERPATH_SOFT:
+ if (glt->flags & TEXF_FORCELINEAR)
+ DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
+ else if (glt->flags & TEXF_FORCENEAREST)
+ DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
+ else if (glt->flags & TEXF_MIPMAP)
+ DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
+ else
+ DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
+ break;
}
Mem_Free(dds);
Host_Error("R_UpdateTexture: no texture supplied");
if (!glt->texnum && !glt->d3dtexture)
{
- Con_Printf("R_UpdateTexture: texture %p \"%s\" in pool %p has not been uploaded yet", (void *)glt, glt->identifier, (void *)glt->pool);
+ Con_DPrintf("R_UpdateTexture: texture %p \"%s\" in pool %p has not been uploaded yet\n", (void *)glt, glt->identifier, (void *)glt->pool);
return;
}
// update part of the texture