X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=gl_textures.c;h=c970f8cae333407d7de4f764f25e20b664e6b6ad;hp=6fe868f45665e5fc4f91a7f82f176591d21c6757;hb=2075ae43356d724bae305ce8fd36ea570718b14a;hpb=65de8e7dbce36a4fd65f98da97d4ea0146195214 diff --git a/gl_textures.c b/gl_textures.c index 6fe868f4..c970f8ca 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -1,14 +1,9 @@ #include "quakedef.h" -#ifdef SUPPORTD3D -#include -extern LPDIRECT3DDEVICE9 vid_d3d9dev; -#endif #include "image.h" #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)"}; @@ -31,26 +26,15 @@ cvar_t gl_texturecompression_q3bspdeluxemaps = {CVAR_SAVE, "gl_texturecompressio cvar_t gl_texturecompression_sky = {CVAR_SAVE, "gl_texturecompression_sky", "0", "whether to compress sky textures"}; cvar_t gl_texturecompression_lightcubemaps = {CVAR_SAVE, "gl_texturecompression_lightcubemaps", "1", "whether to compress light cubemaps (spotlights and other light projection images)"}; 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_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", "1", "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; 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; -int d3d_filter_flatmag = D3DTEXF_LINEAR; -int d3d_filter_flatmix = D3DTEXF_POINT; -int d3d_filter_mipmin = D3DTEXF_LINEAR; -int d3d_filter_mipmag = D3DTEXF_LINEAR; -int d3d_filter_mipmix = D3DTEXF_LINEAR; -int d3d_filter_nomip = false; -#endif static mempool_t *texturemempool; @@ -64,6 +48,7 @@ static memexpandablearray_t texturearray; typedef struct textypeinfo_s { + const char *name; textype_t textype; int inputbytesperpixel; int internalbytesperpixel; @@ -74,26 +59,80 @@ typedef struct textypeinfo_s } textypeinfo_t; - -static textypeinfo_t textype_palette = {TEXTYPE_PALETTE , 1, 4, 4.0f, 3 , GL_BGRA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_palette_alpha = {TEXTYPE_PALETTE , 1, 4, 4.0f, 4 , GL_BGRA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_rgba = {TEXTYPE_RGBA , 4, 4, 4.0f, 3 , GL_RGBA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_rgba_alpha = {TEXTYPE_RGBA , 4, 4, 4.0f, 4 , GL_RGBA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_rgba_compress = {TEXTYPE_RGBA , 4, 4, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , GL_RGBA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_rgba_alpha_compress = {TEXTYPE_RGBA , 4, 4, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_bgra = {TEXTYPE_BGRA , 4, 4, 4.0f, 3 , GL_BGRA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_bgra_alpha = {TEXTYPE_BGRA , 4, 4, 4.0f, 4 , GL_BGRA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_bgra_compress = {TEXTYPE_BGRA , 4, 4, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , GL_BGRA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_bgra_alpha_compress = {TEXTYPE_BGRA , 4, 4, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_BGRA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_shadowmap16 = {TEXTYPE_SHADOWMAP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; -static textypeinfo_t textype_shadowmap24 = {TEXTYPE_SHADOWMAP , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }; -static textypeinfo_t textype_alpha = {TEXTYPE_ALPHA , 1, 4, 4.0f, GL_ALPHA , GL_ALPHA , GL_UNSIGNED_BYTE }; -static textypeinfo_t textype_dxt1 = {TEXTYPE_DXT1 , 4, 0, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , 0 , 0 }; -static textypeinfo_t textype_dxt1a = {TEXTYPE_DXT1A , 4, 0, 0.5f, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0 , 0 }; -static textypeinfo_t textype_dxt3 = {TEXTYPE_DXT3 , 4, 0, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0 , 0 }; -static textypeinfo_t textype_dxt5 = {TEXTYPE_DXT5 , 4, 0, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0 , 0 }; -static textypeinfo_t textype_colorbuffer = {TEXTYPE_COLORBUFFER, 4, 4, 4.0f, 4 , GL_BGRA , GL_UNSIGNED_BYTE }; - +#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}; +static textypeinfo_t textype_shadowmap16_raw = {"shadowmap16_raw", TEXTYPE_SHADOWMAP16_RAW , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; +static textypeinfo_t textype_shadowmap24_comp = {"shadowmap24_comp", TEXTYPE_SHADOWMAP24_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; +static textypeinfo_t textype_shadowmap24_raw = {"shadowmap24_raw", TEXTYPE_SHADOWMAP24_RAW , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; +static textypeinfo_t textype_depth16 = {"depth16", TEXTYPE_DEPTHBUFFER16 , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; +static textypeinfo_t textype_depth24 = {"depth24", TEXTYPE_DEPTHBUFFER24 , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; +static textypeinfo_t textype_depth24stencil8 = {"depth24stencil8", TEXTYPE_DEPTHBUFFER24STENCIL8, 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; +static textypeinfo_t textype_colorbuffer = {"colorbuffer", TEXTYPE_COLORBUFFER , 2, 2, 2.0f, GL_RGB565 , GL_RGBA , GL_UNSIGNED_SHORT_5_6_5}; +static textypeinfo_t textype_colorbuffer16f = {"colorbuffer16f", TEXTYPE_COLORBUFFER16F , 2, 2, 2.0f, GL_RGBA16F , GL_RGBA , GL_HALF_FLOAT}; +static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F , 2, 2, 2.0f, GL_RGBA32F , GL_RGBA , GL_FLOAT}; + +// image formats: +static textypeinfo_t textype_alpha = {"alpha", TEXTYPE_ALPHA , 1, 4, 4.0f, GL_ALPHA , GL_ALPHA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_palette = {"palette", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_palette_alpha = {"palette_alpha", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_rgba = {"rgba", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE }; +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 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; +static textypeinfo_t textype_shadowmap16_raw = {"shadowmap16_raw", TEXTYPE_SHADOWMAP16_RAW , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; +static textypeinfo_t textype_shadowmap24_comp = {"shadowmap24_comp", TEXTYPE_SHADOWMAP24_COMP , 4, 4, 4.0f, GL_DEPTH_COMPONENT24 , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }; +static textypeinfo_t textype_shadowmap24_raw = {"shadowmap24_raw", TEXTYPE_SHADOWMAP24_RAW , 4, 4, 4.0f, GL_DEPTH_COMPONENT24 , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }; +static textypeinfo_t textype_depth16 = {"depth16", TEXTYPE_DEPTHBUFFER16 , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; +static textypeinfo_t textype_depth24 = {"depth24", TEXTYPE_DEPTHBUFFER24 , 4, 4, 4.0f, GL_DEPTH_COMPONENT24 , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }; +static textypeinfo_t textype_depth24stencil8 = {"depth24stencil8", TEXTYPE_DEPTHBUFFER24STENCIL8, 4, 4, 4.0f, GL_DEPTH24_STENCIL8 , GL_DEPTH_STENCIL , GL_UNSIGNED_INT_24_8}; +static textypeinfo_t textype_colorbuffer = {"colorbuffer", TEXTYPE_COLORBUFFER , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_colorbuffer16f = {"colorbuffer16f", TEXTYPE_COLORBUFFER16F , 8, 8, 8.0f, GL_RGBA16F , GL_RGBA , GL_HALF_FLOAT }; +static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F , 16, 16, 16.0f, GL_RGBA32F , GL_RGBA , GL_FLOAT }; + +// image formats: +static textypeinfo_t textype_alpha = {"alpha", TEXTYPE_ALPHA , 1, 4, 4.0f, GL_ALPHA , GL_ALPHA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_palette = {"palette", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGB , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_palette_alpha = {"palette_alpha", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_rgba = {"rgba", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGB , GL_RGBA , GL_UNSIGNED_BYTE }; +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_rgba_compress = {"rgba_compress", TEXTYPE_RGBA , 4, 4, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , GL_RGBA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_rgba_alpha_compress = {"rgba_alpha_compress", TEXTYPE_RGBA , 4, 4, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT , GL_RGBA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_bgra = {"bgra", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGB , 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 }; +static textypeinfo_t textype_bgra_compress = {"bgra_compress", TEXTYPE_BGRA , 4, 4, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_bgra_alpha_compress = {"bgra_alpha_compress", TEXTYPE_BGRA , 4, 4, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_dxt1 = {"dxt1", TEXTYPE_DXT1 , 4, 0, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , 0 , 0 }; +static textypeinfo_t textype_dxt1a = {"dxt1a", TEXTYPE_DXT1A , 4, 0, 0.5f, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT , 0 , 0 }; +static textypeinfo_t textype_dxt3 = {"dxt3", TEXTYPE_DXT3 , 4, 0, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT , 0 , 0 }; +static textypeinfo_t textype_dxt5 = {"dxt5", TEXTYPE_DXT5 , 4, 0, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT , 0 , 0 }; +static textypeinfo_t textype_sRGB_palette = {"sRGB_palette", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_SRGB , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_palette_alpha = {"sRGB_palette_alpha", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_SRGB_ALPHA , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_rgba = {"sRGB_rgba", TEXTYPE_RGBA , 4, 4, 4.0f, GL_SRGB , GL_RGBA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_rgba_alpha = {"sRGB_rgba_alpha", TEXTYPE_RGBA , 4, 4, 4.0f, GL_SRGB_ALPHA , GL_RGBA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_rgba_compress = {"sRGB_rgba_compress", TEXTYPE_RGBA , 4, 4, 0.5f, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT , GL_RGBA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_rgba_alpha_compress = {"sRGB_rgba_alpha_compress", TEXTYPE_RGBA , 4, 4, 1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_bgra = {"sRGB_bgra", TEXTYPE_BGRA , 4, 4, 4.0f, GL_SRGB , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_bgra_alpha = {"sRGB_bgra_alpha", TEXTYPE_BGRA , 4, 4, 4.0f, GL_SRGB_ALPHA , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_bgra_compress = {"sRGB_bgra_compress", TEXTYPE_BGRA , 4, 4, 0.5f, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT , GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_bgra_alpha_compress = {"sRGB_bgra_alpha_compress", TEXTYPE_BGRA , 4, 4, 1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_BGRA , GL_UNSIGNED_BYTE }; +static textypeinfo_t textype_sRGB_dxt1 = {"sRGB_dxt1", TEXTYPE_DXT1 , 4, 0, 0.5f, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT , 0 , 0 }; +static textypeinfo_t textype_sRGB_dxt1a = {"sRGB_dxt1a", TEXTYPE_DXT1A , 4, 0, 0.5f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0 , 0 }; +static textypeinfo_t textype_sRGB_dxt3 = {"sRGB_dxt3", TEXTYPE_DXT3 , 4, 0, 1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0 , 0 }; +static textypeinfo_t textype_sRGB_dxt5 = {"sRGB_dxt5", TEXTYPE_DXT5 , 4, 0, 1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0 , 0 }; +#endif typedef enum gltexturetype_e { @@ -104,16 +143,18 @@ typedef enum gltexturetype_e } gltexturetype_t; -static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP_ARB}; +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_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z }; typedef struct gltexture_s @@ -121,29 +162,14 @@ typedef struct gltexture_s // this portion of the struct is exposed to the R_GetTexture macro for // speed reasons, must be identical in rtexture_t! 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; -#ifdef SUPPORTD3D - qboolean d3disdepthsurface; // for depth/stencil surfaces - int d3dformat; - int d3dusage; - int d3dpool; - int d3daddressu; - int d3daddressv; - int d3daddressw; - int d3dmagfilter; - int d3dminfilter; - int d3dmipfilter; - int d3dmaxmiplevelfilter; - int d3dmipmaplodbias; - int d3dmaxmiplevel; -#endif // dynamic texture stuff [11/22/2007 Black] updatecallback_t updatecallback; - void *updatacallback_data; + void *updatecallback_data; // --- [11/22/2007 Black] // stores backup copy of texture for deferred texture updates (gl_nopartialtextureupdates cvar) @@ -175,7 +201,6 @@ typedef struct gltexture_s // palette if the texture is TEXTYPE_PALETTE const unsigned int *palette; // actual stored texture size after gl_picmip and gl_max_size are applied - // (power of 2 if vid.support.arb_texture_non_power_of_two is not supported) int tilewidth, tileheight, tiledepth; // 1 or 6 depending on texturetype int sides; @@ -212,32 +237,53 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags) { switch(textype) { - case TEXTYPE_DXT1: - return &textype_dxt1; - case TEXTYPE_DXT1A: - return &textype_dxt1a; - case TEXTYPE_DXT3: - return &textype_dxt3; - case TEXTYPE_DXT5: - return &textype_dxt5; - case TEXTYPE_PALETTE: - return (flags & TEXF_ALPHA) ? &textype_palette_alpha : &textype_palette; - case TEXTYPE_RGBA: - if ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.ext_texture_compression_s3tc) - return (flags & TEXF_ALPHA) ? &textype_rgba_alpha_compress : &textype_rgba_compress; - return (flags & TEXF_ALPHA) ? &textype_rgba_alpha : &textype_rgba; - case TEXTYPE_BGRA: - if ((flags & TEXF_COMPRESS) && gl_texturecompression.integer >= 1 && vid.support.ext_texture_compression_s3tc) - return (flags & TEXF_ALPHA) ? &textype_bgra_alpha_compress : &textype_bgra_compress; - return (flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra; - case TEXTYPE_ALPHA: - return &textype_alpha; - case TEXTYPE_SHADOWMAP: - return (flags & TEXF_LOWPRECISION) ? &textype_shadowmap16 : &textype_shadowmap24; - case TEXTYPE_COLORBUFFER: - return &textype_colorbuffer; +#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; + case TEXTYPE_DXT5: return &textype_dxt5; + case TEXTYPE_PALETTE: return (flags & TEXF_ALPHA) ? &textype_palette_alpha : &textype_palette; + case TEXTYPE_RGBA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_rgba_alpha_compress : &textype_rgba_compress) : ((flags & TEXF_ALPHA) ? &textype_rgba_alpha : &textype_rgba); + case TEXTYPE_BGRA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_bgra_alpha_compress : &textype_bgra_compress) : ((flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra); + 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; + case TEXTYPE_SRGB_DXT1: return &textype_sRGB_dxt1; + case TEXTYPE_SRGB_DXT1A: return &textype_sRGB_dxt1a; + case TEXTYPE_SRGB_DXT3: return &textype_sRGB_dxt3; + case TEXTYPE_SRGB_DXT5: return &textype_sRGB_dxt5; + 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"); + Host_Error("R_GetTexTypeInfo: unknown texture format %i with flags %x", (int)textype, flags); break; } return NULL; @@ -266,13 +312,13 @@ void R_MakeTextureDynamic(rtexture_t *rt, updatecallback_t updatecallback, void glt->flags |= GLTEXF_DYNAMIC; glt->updatecallback = updatecallback; - glt->updatacallback_data = data; + glt->updatecallback_data = data; } static void R_UpdateDynamicTexture(gltexture_t *glt) { glt->dirty = false; if( glt->updatecallback ) { - glt->updatecallback( (rtexture_t*) glt, glt->updatacallback_data ); + glt->updatecallback( (rtexture_t*) glt, glt->updatecallback_data ); } } @@ -297,40 +343,22 @@ void R_FreeTexture(rtexture_t *rt) else Host_Error("R_FreeTexture: texture \"%s\" not linked in pool", glt->identifier); + R_Mesh_ClearBindingsForTexture(glt->texnum); + switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: 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; - case RENDERPATH_SOFT: - if (glt->texnum) - DPSOFTRAST_Texture_Free(glt->texnum); + if (glt->renderbuffernum) + { + CHECKGLERROR + qglDeleteRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR + } break; } @@ -379,39 +407,19 @@ typedef struct glmode_s { 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, 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} + {"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} }; -#ifdef SUPPORTD3D -typedef struct d3dmode_s -{ - const char *name; - int m1, m2; -} -d3dmode_t; - -static d3dmode_t d3dmodes[6] = -{ - {"GL_NEAREST", D3DTEXF_POINT, D3DTEXF_POINT}, - {"GL_LINEAR", D3DTEXF_LINEAR, D3DTEXF_POINT}, - {"GL_NEAREST_MIPMAP_NEAREST", D3DTEXF_POINT, D3DTEXF_POINT}, - {"GL_LINEAR_MIPMAP_NEAREST", D3DTEXF_LINEAR, D3DTEXF_POINT}, - {"GL_NEAREST_MIPMAP_LINEAR", D3DTEXF_POINT, D3DTEXF_LINEAR}, - {"GL_LINEAR_MIPMAP_LINEAR", D3DTEXF_LINEAR, D3DTEXF_LINEAR} -}; -#endif - static void GL_TextureMode_f (void) { int i; @@ -447,15 +455,10 @@ static void GL_TextureMode_f (void) 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_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: // change all the existing mipmap texture objects // FIXME: force renderer(/client/something?) restart instead? CHECKGLERROR @@ -483,56 +486,6 @@ static void GL_TextureMode_f (void) } } break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - d3d_filter_flatmin = d3dmodes[i].m1; - d3d_filter_flatmag = d3dmodes[i].m1; - d3d_filter_flatmix = D3DTEXF_POINT; - d3d_filter_mipmin = d3dmodes[i].m1; - d3d_filter_mipmag = d3dmodes[i].m1; - d3d_filter_mipmix = d3dmodes[i].m2; - d3d_filter_nomip = i < 2; - if (gl_texture_anisotropy.integer > 1 && i == 5) - d3d_filter_mipmin = d3d_filter_mipmag = D3DTEXF_ANISOTROPIC; - for (pool = gltexturepoolchain;pool;pool = pool->next) - { - for (glt = pool->gltchain;glt;glt = glt->chain) - { - // only update already uploaded images - if (glt->d3dtexture && !glt->d3disdepthsurface && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR)))) - { - if (glt->flags & TEXF_MIPMAP) - { - glt->d3dminfilter = d3d_filter_mipmin; - glt->d3dmagfilter = d3d_filter_mipmag; - glt->d3dmipfilter = d3d_filter_mipmix; - glt->d3dmaxmiplevelfilter = 0; - } - else - { - glt->d3dminfilter = d3d_filter_flatmin; - glt->d3dmagfilter = d3d_filter_flatmag; - glt->d3dmipfilter = d3d_filter_flatmix; - glt->d3dmaxmiplevelfilter = 0; - } - } - } - } -#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; - 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; } } @@ -559,43 +512,9 @@ static void GL_Texture_CalcImageSize(int texturetype, int flags, int miplevel, i break; } - if (vid.support.arb_texture_non_power_of_two) - { - width2 = min(inwidth >> picmip, maxsize); - height2 = min(inheight >> picmip, maxsize); - depth2 = min(indepth >> picmip, maxsize); - } - else - { - 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); - } - - switch(vid.renderpath) - { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: - case RENDERPATH_D3D10: - case RENDERPATH_D3D11: - case RENDERPATH_SOFT: - 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) - { - width2 = max(width2, 2); - height2 = max(height2, 2); - } -#endif - break; - } + width2 = min(inwidth >> picmip, maxsize); + height2 = min(inheight >> picmip, maxsize); + depth2 = min(indepth >> picmip, maxsize); miplevels = 1; if (flags & TEXF_MIPMAP) @@ -662,7 +581,7 @@ void R_TextureStats_Print(qboolean printeach, qboolean printpool, qboolean print for (glt = pool->gltchain;glt;glt = glt->chain) { glsize = R_CalcTexelDataSize(glt); - isloaded = glt->texnum != 0; + isloaded = glt->texnum != 0 || glt->renderbuffernum != 0; pooltotal++; pooltotalt += glsize; pooltotalp += glt->inputdatasize; @@ -673,7 +592,7 @@ void R_TextureStats_Print(qboolean printeach, qboolean printpool, qboolean print poolloadedp += glt->inputdatasize; } if (printeach) - Con_Printf("%c%4i%c%c%4i%c %s %s %s %s\n", isloaded ? '[' : ' ', (glsize + 1023) / 1024, isloaded ? ']' : ' ', glt->inputtexels ? '[' : ' ', (glt->inputdatasize + 1023) / 1024, glt->inputtexels ? ']' : ' ', isloaded ? "loaded" : " ", (glt->flags & TEXF_MIPMAP) ? "mip" : " ", (glt->flags & TEXF_ALPHA) ? "alpha" : " ", glt->identifier); + Con_Printf("%c%4i%c%c%4i%c %-24s %s %s %s %s\n", isloaded ? '[' : ' ', (glsize + 1023) / 1024, isloaded ? ']' : ' ', glt->inputtexels ? '[' : ' ', (glt->inputdatasize + 1023) / 1024, glt->inputtexels ? ']' : ' ', glt->textype->name, isloaded ? "loaded" : " ", (glt->flags & TEXF_MIPMAP) ? "mip" : " ", (glt->flags & TEXF_ALPHA) ? "alpha" : " ", glt->identifier); } if (printpool) Con_Printf("texturepool %10p total: %i (%.3fMB, %.3fMB original), uploaded %i (%.3fMB, %.3fMB original), upload on demand %i (%.3fMB, %.3fMB original)\n", (void *)pool, pooltotal, pooltotalt / 1048576.0, pooltotalp / 1048576.0, poolloaded, poolloadedt / 1048576.0, poolloadedp / 1048576.0, pooltotal - poolloaded, (pooltotalt - poolloadedt) / 1048576.0, (pooltotalp - poolloadedp) / 1048576.0); @@ -697,25 +616,13 @@ static void r_textures_start(void) { switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: // LordHavoc: allow any alignment CHECKGLERROR qglPixelStorei(GL_UNPACK_ALIGNMENT, 1);CHECKGLERROR qglPixelStorei(GL_PACK_ALIGNMENT, 1);CHECKGLERROR break; - case RENDERPATH_D3D9: - 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; - case RENDERPATH_SOFT: - break; } texturemempool = Mem_AllocPool("texture management", 0, NULL); @@ -756,7 +663,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); @@ -764,31 +671,8 @@ static void r_textures_devicelost(void) continue; switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: - 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; - case RENDERPATH_SOFT: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: break; } } @@ -798,7 +682,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); @@ -806,45 +690,8 @@ static void r_textures_devicerestored(void) continue; switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: - break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - { - HRESULT d3dresult; - 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!"); - } - else if (glt->sides == 6) - { - if (FAILED(d3dresult = IDirect3DDevice9_CreateCubeTexture(vid_d3d9dev, glt->tilewidth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DCubeTexture9 **)&glt->d3dtexture, NULL))) - Sys_Error("IDirect3DDevice9_CreateCubeTexture failed!"); - } - else - { - if (FAILED(d3dresult = IDirect3DDevice9_CreateTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DTexture9 **)&glt->d3dtexture, NULL))) - Sys_Error("IDirect3DDevice9_CreateTexture failed!"); - } - } -#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; - case RENDERPATH_SOFT: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: break; } } @@ -876,6 +723,7 @@ void R_Textures_Init (void) Cvar_RegisterVariable (&gl_texturecompression_sky); Cvar_RegisterVariable (&gl_texturecompression_lightcubemaps); Cvar_RegisterVariable (&gl_texturecompression_reflectmask); + Cvar_RegisterVariable (&gl_texturecompression_sprites); Cvar_RegisterVariable (&gl_nopartialtextureupdates); Cvar_RegisterVariable (&r_texture_dds_load_alphamode); Cvar_RegisterVariable (&r_texture_dds_load_logfailure); @@ -886,7 +734,10 @@ void R_Textures_Init (void) void R_Textures_Frame (void) { +#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT static int old_aniso = 0; + static qboolean first_time_aniso = true; +#endif // could do procedural texture animation here, if we keep track of which // textures were accessed this frame... @@ -904,6 +755,7 @@ void R_Textures_Frame (void) colorconvertbuffer = NULL; } +#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT if (old_aniso != gl_texture_anisotropy.integer) { gltexture_t *glt; @@ -916,10 +768,14 @@ void R_Textures_Frame (void) switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: + // ignore the first difference, any textures loaded by now probably had the same aniso value + if (first_time_aniso) + { + first_time_aniso = false; + break; + } CHECKGLERROR GL_ActiveTexture(0); for (pool = gltexturepoolchain;pool;pool = pool->next) @@ -939,16 +795,12 @@ void R_Textures_Frame (void) } } break; - case RENDERPATH_D3D9: - case RENDERPATH_D3D10: - case RENDERPATH_D3D11: - case RENDERPATH_SOFT: - break; } } +#endif } -void R_MakeResizeBufferBigger(int size) +static void R_MakeResizeBufferBigger(int size) { if (resizebuffersize < size) { @@ -971,6 +823,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); @@ -978,12 +831,15 @@ 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 if (gltexturetypedimensions[texturetype] >= 3) { qglTexParameteri(textureenum, GL_TEXTURE_WRAP_R, wrapmode);CHECKGLERROR } +#endif CHECKGLERROR if (!gl_filter_force && flags & TEXF_FORCENEAREST) @@ -1030,22 +886,23 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR } - if (textype == TEXTYPE_SHADOWMAP) +#ifndef USE_GLES2 + switch(textype) { - if (vid.support.arb_shadow) - { - if (flags & TEXF_COMPARE) - { - qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR - } - else - { - qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR - } - qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR - } - qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR + case TEXTYPE_SHADOWMAP16_COMP: + case TEXTYPE_SHADOWMAP24_COMP: + qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);CHECKGLERROR + qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);CHECKGLERROR + break; + case TEXTYPE_SHADOWMAP16_RAW: + case TEXTYPE_SHADOWMAP24_RAW: + qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE, GL_NONE);CHECKGLERROR + qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);CHECKGLERROR + break; + default: + break; } +#endif CHECKGLERROR } @@ -1071,10 +928,8 @@ static void R_UploadPartialTexture(gltexture_t *glt, const unsigned char *data, switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: { int oldbindtexnum; CHECKGLERROR @@ -1086,35 +941,6 @@ static void R_UploadPartialTexture(gltexture_t *glt, const unsigned char *data, qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR } break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - { - RECT d3drect; - D3DLOCKED_RECT d3dlockedrect; - int y; - memset(&d3drect, 0, sizeof(d3drect)); - d3drect.left = fragx; - d3drect.top = fragy; - d3drect.right = fragx+fragwidth; - d3drect.bottom = fragy+fragheight; - if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, 0, &d3dlockedrect, &d3drect, 0) == D3D_OK && d3dlockedrect.pBits) - { - for (y = 0;y < fragheight;y++) - memcpy((unsigned char *)d3dlockedrect.pBits + d3dlockedrect.Pitch * y, data + fragwidth*glt->bytesperpixel * y, fragwidth*glt->bytesperpixel); - IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, 0); - } - } -#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; - case RENDERPATH_SOFT: - DPSOFTRAST_Texture_UpdatePartial(glt->texnum, 0, data, fragx, fragy, fragwidth, fragheight); - break; } } @@ -1135,191 +961,106 @@ static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data) for (width = glt->tilewidth;width < glt->inputwidth ;width <<= 1); for (height = glt->tileheight;height < glt->inputheight;height <<= 1); for (depth = glt->tiledepth;depth < glt->inputdepth ;depth <<= 1); - R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); if (prevbuffer == NULL) { width = glt->tilewidth; height = glt->tileheight; depth = glt->tiledepth; - memset(resizebuffer, 0, width * height * depth * glt->sides * glt->bytesperpixel); - prevbuffer = resizebuffer; - } - else if (glt->textype->textype == TEXTYPE_PALETTE) - { - // promote paletted to BGRA, so we only have to worry about BGRA in the rest of this code - Image_Copy8bitBGRA(prevbuffer, colorconvertbuffer, glt->inputwidth * glt->inputheight * glt->inputdepth * glt->sides, glt->palette); - prevbuffer = colorconvertbuffer; +// R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); +// memset(resizebuffer, 0, width * height * depth * glt->sides * glt->bytesperpixel); +// prevbuffer = resizebuffer; } - - if (glt->flags & TEXF_RGBMULTIPLYBYALPHA) + else { - // multiply RGB channels by A channel before uploading - int alpha; - for (i = 0;i < width*height*depth*4;i += 4) + if (glt->textype->textype == TEXTYPE_PALETTE) { - 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; + // promote paletted to BGRA, so we only have to worry about BGRA in the rest of this code + R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); + Image_Copy8bitBGRA(prevbuffer, colorconvertbuffer, glt->inputwidth * glt->inputheight * glt->inputdepth * glt->sides, glt->palette); + prevbuffer = colorconvertbuffer; + } + if (glt->flags & TEXF_RGBMULTIPLYBYALPHA) + { + // multiply RGB channels by A channel before uploading + int alpha; + R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); + for (i = 0;i < glt->inputwidth*glt->inputheight*glt->inputdepth*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) + { + R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); + Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer); + prevbuffer = resizebuffer; + } + // apply mipmap reduction algorithm to get down to picmip/max_size + while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth) + { + R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); + Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth); + prevbuffer = resizebuffer; } - prevbuffer = colorconvertbuffer; - } - - // scale up to a power of 2 size (if appropriate) - 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; - } - // apply mipmap reduction algorithm to get down to 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; } // do the appropriate upload type... switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: - CHECKGLERROR + case RENDERPATH_GL32: + case RENDERPATH_GLES2: + if (glt->texnum) // not renderbuffers + { + CHECKGLERROR - // we need to restore the texture binding after finishing the upload - GL_ActiveTexture(0); - oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]); - qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR + // we need to restore the texture binding after finishing the upload + GL_ActiveTexture(0); + oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]); + qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR - if (qglGetCompressedTexImageARB) - { +#ifndef USE_GLES2 if (gl_texturecompression.integer >= 2) - qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST); + qglHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); else - qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_FASTEST); + qglHint(GL_TEXTURE_COMPRESSION_HINT, GL_FASTEST); CHECKGLERROR - } - switch(glt->texturetype) - { - case GLTEXTURETYPE_2D: - qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR - if (glt->flags & TEXF_MIPMAP) - { - while (width > 1 || height > 1 || depth > 1) - { - Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1); - prevbuffer = resizebuffer; - qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR - } - } - break; - case GLTEXTURETYPE_3D: - qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR - if (glt->flags & TEXF_MIPMAP) - { - while (width > 1 || height > 1 || depth > 1) - { - Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1); - prevbuffer = resizebuffer; - qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR - } - } - break; - case GLTEXTURETYPE_CUBEMAP: - // convert and upload each side in turn, - // from a continuous block of input texels - 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; - } - mip = 0; - qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR - if (glt->flags & TEXF_MIPMAP) - { - while (width > 1 || height > 1 || depth > 1) - { - Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1); - prevbuffer = resizebuffer; - qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR - } - } - } - break; - } - GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype); - qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR - break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - if (!(glt->flags & TEXF_RENDERTARGET)) - { - D3DLOCKED_RECT d3dlockedrect; - D3DLOCKED_BOX d3dlockedbox; +#endif switch(glt->texturetype) { case GLTEXTURETYPE_2D: - if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits) - { - if (prevbuffer) - memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel); - else - memset(d3dlockedrect.pBits, 255, width*height*glt->bytesperpixel); - IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip); - } - mip++; - if ((glt->flags & TEXF_MIPMAP) && prevbuffer) + qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR + if (glt->flags & TEXF_MIPMAP) { while (width > 1 || height > 1 || depth > 1) { + R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1); prevbuffer = resizebuffer; - if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits) - { - memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel); - IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip); - } - mip++; + qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR } } break; case GLTEXTURETYPE_3D: - if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits) - { - // we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes - memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel); - IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip); - } - mip++; +#ifndef USE_GLES2 + qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR if (glt->flags & TEXF_MIPMAP) { while (width > 1 || height > 1 || depth > 1) { + R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1); prevbuffer = resizebuffer; - if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits) - { - // we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes - memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel); - IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip); - } - mip++; + qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR } } +#endif break; case GLTEXTURETYPE_CUBEMAP: // convert and upload each side in turn, @@ -1331,139 +1072,35 @@ static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data) texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel; if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth) { + R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); 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) { + R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth); prevbuffer = resizebuffer; } mip = 0; - if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits) - { - memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel); - IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip); - } - mip++; + qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR if (glt->flags & TEXF_MIPMAP) { while (width > 1 || height > 1 || depth > 1) { + R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel); Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1); prevbuffer = resizebuffer; - if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits) - { - memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel); - IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip); - } - mip++; + qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR } } } break; } + GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype); + qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR } - glt->d3daddressw = 0; - if (glt->flags & TEXF_CLAMP) - { - glt->d3daddressu = D3DTADDRESS_CLAMP; - glt->d3daddressv = D3DTADDRESS_CLAMP; - if (glt->tiledepth > 1) - glt->d3daddressw = D3DTADDRESS_CLAMP; - } - else - { - glt->d3daddressu = D3DTADDRESS_WRAP; - glt->d3daddressv = D3DTADDRESS_WRAP; - if (glt->tiledepth > 1) - glt->d3daddressw = D3DTADDRESS_WRAP; - } - glt->d3dmipmaplodbias = 0; - glt->d3dmaxmiplevel = 0; - glt->d3dmaxmiplevelfilter = d3d_filter_nomip ? 0 : glt->d3dmaxmiplevel; - if (glt->flags & TEXF_FORCELINEAR) - { - glt->d3dminfilter = D3DTEXF_LINEAR; - glt->d3dmagfilter = D3DTEXF_LINEAR; - glt->d3dmipfilter = D3DTEXF_POINT; - } - else if (glt->flags & TEXF_FORCENEAREST) - { - glt->d3dminfilter = D3DTEXF_POINT; - glt->d3dmagfilter = D3DTEXF_POINT; - glt->d3dmipfilter = D3DTEXF_POINT; - } - else if (glt->flags & TEXF_MIPMAP) - { - glt->d3dminfilter = d3d_filter_mipmin; - glt->d3dmagfilter = d3d_filter_mipmag; - glt->d3dmipfilter = d3d_filter_mipmix; - } - else - { - glt->d3dminfilter = d3d_filter_flatmin; - glt->d3dmagfilter = d3d_filter_flatmag; - glt->d3dmipfilter = d3d_filter_flatmix; - } -#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; - 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; } } @@ -1475,19 +1112,80 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden gltexturepool_t *pool = (gltexturepool_t *)rtexturepool; textypeinfo_t *texinfo, *texinfo2; unsigned char *temppixels = NULL; + qboolean swaprb; if (cls.state == ca_dedicated) return NULL; - if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map) + // see if we need to swap red and blue (BGRA <-> RGBA conversion) + if (textype == TEXTYPE_PALETTE && vid.forcetextype == TEXTYPE_RGBA) { - Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n"); - return NULL; + int numpixels = width * height * depth * sides; + size = numpixels * 4; + temppixels = (unsigned char *)Mem_Alloc(tempmempool, size); + if (data) + { + const unsigned char *p; + unsigned char *o = temppixels; + for (i = 0;i < numpixels;i++, o += 4) + { + p = (const unsigned char *)palette + 4*data[i]; + o[0] = p[2]; + o[1] = p[1]; + o[2] = p[0]; + o[3] = p[3]; + } + } + data = temppixels; + textype = TEXTYPE_RGBA; } - if (texturetype == GLTEXTURETYPE_3D && !vid.support.ext_texture_3d) + swaprb = false; + switch(textype) { - Con_Printf ("R_LoadTexture: 3d texture not supported by driver\n"); - return NULL; + case TEXTYPE_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_BGRA;} break; + case TEXTYPE_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_RGBA;} break; + case TEXTYPE_SRGB_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_SRGB_BGRA;} break; + case TEXTYPE_SRGB_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_SRGB_RGBA;} break; + default: break; + } + if (swaprb) + { + // swap bytes + static int rgbaswapindices[4] = {2, 1, 0, 3}; + size = width * height * depth * sides * 4; + temppixels = (unsigned char *)Mem_Alloc(tempmempool, size); + if (data) + Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices); + data = temppixels; + } + + // if sRGB texture formats are not supported, convert input to linear and upload as normal types + if (!vid.support.ext_texture_srgb) + { + qboolean convertsRGB = false; + switch(textype) + { + case TEXTYPE_SRGB_DXT1: textype = TEXTYPE_DXT1 ;convertsRGB = true;break; + 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_RGBA: textype = TEXTYPE_RGBA ;convertsRGB = true;break; + case TEXTYPE_SRGB_BGRA: textype = TEXTYPE_BGRA ;convertsRGB = true;break; + default: + break; + } + if (convertsRGB && data) + { + size = width * height * depth * sides * 4; + if (!temppixels) + { + temppixels = (unsigned char *)Mem_Alloc(tempmempool, size); + memcpy(temppixels, data, size); + data = temppixels; + } + Image_MakeLinearColorsFromsRGB(temppixels, temppixels, width*height*depth*sides); + } } texinfo = R_GetTexTypeInfo(textype, flags); @@ -1498,21 +1196,11 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden return NULL; } - if (textype == TEXTYPE_RGBA) - { - // swap bytes - static int rgbaswapindices[4] = {2, 1, 0, 3}; - textype = TEXTYPE_BGRA; - texinfo = R_GetTexTypeInfo(textype, flags); - temppixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * depth * sides * 4); - Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices); - data = temppixels; - } - // clear the alpha flag if the texture has no transparent pixels switch(textype) { case TEXTYPE_PALETTE: + case TEXTYPE_SRGB_PALETTE: if (flags & TEXF_ALPHA) { flags &= ~TEXF_ALPHA; @@ -1531,6 +1219,8 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden break; case TEXTYPE_RGBA: case TEXTYPE_BGRA: + case TEXTYPE_SRGB_RGBA: + case TEXTYPE_SRGB_BGRA: if (flags & TEXF_ALPHA) { flags &= ~TEXF_ALPHA; @@ -1547,19 +1237,28 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden } } break; - case TEXTYPE_SHADOWMAP: + case TEXTYPE_SHADOWMAP16_COMP: + case TEXTYPE_SHADOWMAP16_RAW: + case TEXTYPE_SHADOWMAP24_COMP: + case TEXTYPE_SHADOWMAP24_RAW: break; case TEXTYPE_DXT1: + case TEXTYPE_SRGB_DXT1: break; case TEXTYPE_DXT1A: + case TEXTYPE_SRGB_DXT1A: case TEXTYPE_DXT3: + case TEXTYPE_SRGB_DXT3: case TEXTYPE_DXT5: + case TEXTYPE_SRGB_DXT5: flags |= TEXF_ALPHA; break; case TEXTYPE_ALPHA: flags |= TEXF_ALPHA; break; case TEXTYPE_COLORBUFFER: + case TEXTYPE_COLORBUFFER16F: + case TEXTYPE_COLORBUFFER32F: flags |= TEXF_ALPHA; break; default: @@ -1594,10 +1293,11 @@ 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; - glt->updatacallback_data = NULL; + glt->updatecallback_data = NULL; GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth, &glt->miplevels); @@ -1605,90 +1305,11 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden // data may be NULL (blank texture for dynamic rendering) switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: CHECKGLERROR qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - { - D3DFORMAT d3dformat; - D3DPOOL d3dpool; - DWORD d3dusage; - HRESULT d3dresult; - d3dusage = 0; - d3dpool = D3DPOOL_MANAGED; - if (flags & TEXF_RENDERTARGET) - { - d3dusage |= D3DUSAGE_RENDERTARGET; - d3dpool = D3DPOOL_DEFAULT; - } - switch(textype) - { - case TEXTYPE_PALETTE: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break; - case TEXTYPE_RGBA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8B8G8R8 : D3DFMT_X8B8G8R8;break; - case TEXTYPE_BGRA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break; - case TEXTYPE_COLORBUFFER: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break; - case TEXTYPE_SHADOWMAP: d3dformat = D3DFMT_D16;d3dusage = D3DUSAGE_DEPTHSTENCIL;break; // note: can not use D3DUSAGE_RENDERTARGET here - case TEXTYPE_ALPHA: d3dformat = D3DFMT_A8;break; - default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTexture: unsupported texture type %i when picking D3DFMT", (int)textype);break; - } - glt->d3dformat = d3dformat; - glt->d3dusage = d3dusage; - glt->d3dpool = d3dpool; - 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!"); - } - else if (glt->sides == 6) - { - if (FAILED(d3dresult = IDirect3DDevice9_CreateCubeTexture(vid_d3d9dev, glt->tilewidth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DCubeTexture9 **)&glt->d3dtexture, NULL))) - Sys_Error("IDirect3DDevice9_CreateCubeTexture failed!"); - } - else - { - if (FAILED(d3dresult = IDirect3DDevice9_CreateTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DTexture9 **)&glt->d3dtexture, NULL))) - Sys_Error("IDirect3DDevice9_CreateTexture failed!"); - } - } -#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; - 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); @@ -1721,25 +1342,75 @@ rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *ident return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, miplevel, textype, GLTEXTURETYPE_CUBEMAP, data, palette); } -static int R_ShadowMapTextureFlags(int precision, qboolean filter) +rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype, qboolean filter) { - int flags = TEXF_RENDERTARGET | TEXF_CLAMP; - if (filter) - flags |= TEXF_FORCELINEAR | TEXF_COMPARE; - else - flags |= TEXF_FORCENEAREST; - if (precision <= 16) - flags |= TEXF_LOWPRECISION; - return flags; + return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_RENDERTARGET | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR : TEXF_FORCENEAREST), -1, textype, GLTEXTURETYPE_2D, NULL, NULL); } -rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter) +rtexture_t *R_LoadTextureRenderBuffer(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype) { - return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), -1, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL); + gltexture_t *glt; + gltexturepool_t *pool = (gltexturepool_t *)rtexturepool; + textypeinfo_t *texinfo; + + if (cls.state == ca_dedicated) + return NULL; + + texinfo = R_GetTexTypeInfo(textype, TEXF_RENDERTARGET | TEXF_CLAMP); + + glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray); + if (identifier) + strlcpy (glt->identifier, identifier, sizeof(glt->identifier)); + glt->pool = pool; + glt->chain = pool->gltchain; + pool->gltchain = glt; + glt->inputwidth = width; + glt->inputheight = height; + glt->inputdepth = 1; + glt->flags = TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_FORCENEAREST; + glt->miplevel = 0; + glt->textype = texinfo; + glt->texturetype = textype; + glt->inputdatasize = width*height*texinfo->internalbytesperpixel; + glt->palette = NULL; + glt->glinternalformat = texinfo->glinternalformat; + glt->glformat = texinfo->glformat; + glt->gltype = texinfo->gltype; + glt->bytesperpixel = texinfo->internalbytesperpixel; + glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1; + glt->texnum = 0; + glt->dirty = false; + glt->glisdepthstencil = textype == TEXTYPE_DEPTHBUFFER24STENCIL8; + glt->gltexturetypeenum = GL_TEXTURE_2D; + // init the dynamic texture attributes, too [11/22/2007 Black] + glt->updatecallback = NULL; + glt->updatecallback_data = NULL; + + GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth, &glt->miplevels); + + // upload the texture + // data may be NULL (blank texture for dynamic rendering) + switch(vid.renderpath) + { + case RENDERPATH_GL32: + case RENDERPATH_GLES2: + 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 + qglBindRenderbuffer(GL_RENDERBUFFER, 0);CHECKGLERROR + break; + } + + return (rtexture_t *)glt; } int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha) { +#ifdef USE_GLES2 + return -1; // unsupported on this platform +#else gltexture_t *glt = (gltexture_t *)rt; unsigned char *dds; int oldbindtexnum; @@ -1789,7 +1460,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) + if ((glt->flags & TEXF_MIPMAP) && !(glt->tilewidth == 1 && glt->tileheight == 1)) { for (mip = 1;mip < 16;mip++) { @@ -1832,11 +1503,11 @@ int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipunco if(hasalpha) dds_format_flags |= 0x1; // DDPF_ALPHAPIXELS memcpy(dds, "DDS ", 4); - StoreLittleLong(dds+4, ddssize); + StoreLittleLong(dds+4, 124); // http://msdn.microsoft.com/en-us/library/bb943982%28v=vs.85%29.aspx says so StoreLittleLong(dds+8, dds_flags); StoreLittleLong(dds+12, mipinfo[0][1]); // height StoreLittleLong(dds+16, mipinfo[0][0]); // width - StoreLittleLong(dds+24, 1); // depth + StoreLittleLong(dds+24, 0); // depth StoreLittleLong(dds+28, mipmaps); // mipmaps StoreLittleLong(dds+76, 32); // format size StoreLittleLong(dds+80, dds_format_flags); @@ -1848,7 +1519,7 @@ int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipunco memcpy(dds+84, ddsfourcc, 4); for (mip = 0;mip < mipmaps;mip++) { - qglGetCompressedTexImageARB(gltexturetypeenums[glt->texturetype], mip, dds + mipinfo[mip][3]);CHECKGLERROR + qglGetCompressedTexImage(gltexturetypeenums[glt->texturetype], mip, dds + mipinfo[mip][3]);CHECKGLERROR } } else @@ -1865,9 +1536,15 @@ int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipunco ret = FS_WriteFile(filename, dds, ddssize); Mem_Free(dds); return ret ? ddssize : -5; +#endif } -rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, 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; @@ -1878,23 +1555,169 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen gltexturepool_t *pool = (gltexturepool_t *)rtexturepool; textypeinfo_t *texinfo; int mip, mipwidth, mipheight, mipsize, mipsize_total; - unsigned int c; + unsigned int c, r, g, b; GLint oldbindtexnum = 0; - const unsigned char *mippixels, *ddspixels, *mippixels_start; + unsigned char *mippixels; + unsigned char *mippixels_start; + unsigned char *ddspixels; unsigned char *dds; fs_offset_t ddsfilesize; unsigned int ddssize; - qboolean force_swdecode = (r_texture_dds_swdecode.integer > 1); + qboolean force_swdecode; +#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 } @@ -1922,6 +1745,7 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen { // very sloppy BGRA 32bit identification textype = TEXTYPE_BGRA; + flags &= ~TEXF_COMPRESS; // don't let the textype be wrong bytesperblock = 0; bytesperpixel = 4; size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(dds_width, dds_height), bytesperpixel); @@ -1957,9 +1781,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) @@ -1976,6 +1800,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; @@ -2045,10 +1871,22 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen return NULL; } + // when requesting a non-alpha texture and we have DXT3/5, convert to DXT1 + if(!(flags & TEXF_ALPHA) && (textype == TEXTYPE_DXT3 || textype == TEXTYPE_DXT5)) + { + textype = TEXTYPE_DXT1; + bytesperblock = 8; + ddssize -= 128; + ddssize /= 2; + for (i = 0;i < (int)ddssize;i += bytesperblock) + memcpy(&ddspixels[i], &ddspixels[(i<<1)+8], 8); + ddssize += 128; + } + force_swdecode = false; if(bytesperblock) { - if(vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc) + if(vid.support.ext_texture_compression_s3tc) { if(r_texture_dds_swdecode.integer > 1) force_swdecode = true; @@ -2159,7 +1997,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) @@ -2170,11 +2008,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; @@ -2189,7 +2027,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; @@ -2197,6 +2035,101 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen } } + // if we want sRGB, convert now + if(srgb) + { + if (vid.support.ext_texture_srgb) + { + switch(textype) + { + case TEXTYPE_DXT1: textype = TEXTYPE_SRGB_DXT1 ;break; + case TEXTYPE_DXT1A: textype = TEXTYPE_SRGB_DXT1A ;break; + case TEXTYPE_DXT3: textype = TEXTYPE_SRGB_DXT3 ;break; + case TEXTYPE_DXT5: textype = TEXTYPE_SRGB_DXT5 ;break; + case TEXTYPE_RGBA: textype = TEXTYPE_SRGB_RGBA ;break; + default: + break; + } + } + else + { + switch(textype) + { + case TEXTYPE_DXT1: + case TEXTYPE_DXT1A: + case TEXTYPE_DXT3: + case TEXTYPE_DXT5: + { + for (i = bytesperblock == 16 ? 8 : 0;i < mipsize_total;i += bytesperblock) + { + int c0, c1, c0new, c1new; + c0 = mippixels_start[i] + 256*mippixels_start[i+1]; + r = ((c0 >> 11) & 0x1F); + g = ((c0 >> 5) & 0x3F); + b = ((c0 ) & 0x1F); + r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + c0new = (r << 11) | (g << 5) | b; + c1 = mippixels_start[i+2] + 256*mippixels_start[i+3]; + r = ((c1 >> 11) & 0x1F); + g = ((c1 >> 5) & 0x3F); + b = ((c1 ) & 0x1F); + r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB + c1new = (r << 11) | (g << 5) | b; + // swap the colors if needed to fix order + if(c0 > c1) // thirds + { + if(c0new < c1new) + { + c = c0new; + c0new = c1new; + c1new = c; + if(c0new == c1new) + mippixels_start[i+4] ^= 0x55; + mippixels_start[i+5] ^= 0x55; + mippixels_start[i+6] ^= 0x55; + mippixels_start[i+7] ^= 0x55; + } + else if(c0new == c1new) + { + mippixels_start[i+4] = 0x00; + mippixels_start[i+5] = 0x00; + mippixels_start[i+6] = 0x00; + mippixels_start[i+7] = 0x00; + } + } + else // half + transparent + { + if(c0new > c1new) + { + c = c0new; + c0new = c1new; + c1new = c; + mippixels_start[i+4] ^= (~mippixels_start[i+4] >> 1) & 0x55; + mippixels_start[i+5] ^= (~mippixels_start[i+5] >> 1) & 0x55; + mippixels_start[i+6] ^= (~mippixels_start[i+6] >> 1) & 0x55; + mippixels_start[i+7] ^= (~mippixels_start[i+7] >> 1) & 0x55; + } + } + mippixels_start[i] = c0new & 255; + mippixels_start[i+1] = c0new >> 8; + mippixels_start[i+2] = c1new & 255; + mippixels_start[i+3] = c1new >> 8; + } + } + break; + case TEXTYPE_RGBA: + Image_MakeLinearColorsFromsRGB(mippixels, mippixels, mipsize_total / bytesperblock); + break; + default: + break; + } + } + } + // when not requesting mipmaps, do not load them if(!(flags & TEXF_MIPMAP)) dds_miplevels = 0; @@ -2237,45 +2170,14 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen // create the texture object switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: CHECKGLERROR GL_ActiveTexture(0); oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]); qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - { - D3DFORMAT d3dformat; - D3DPOOL d3dpool; - DWORD d3dusage; - switch(textype) - { - case TEXTYPE_BGRA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break; - case TEXTYPE_DXT1: case TEXTYPE_DXT1A: d3dformat = D3DFMT_DXT1;break; - case TEXTYPE_DXT3: d3dformat = D3DFMT_DXT3;break; - case TEXTYPE_DXT5: d3dformat = D3DFMT_DXT5;break; - default: d3dformat = D3DFMT_A8R8G8B8;Host_Error("R_LoadTextureDDSFile: unsupported texture type %i when picking D3DFMT", (int)textype);break; - } - d3dusage = 0; - d3dpool = D3DPOOL_MANAGED; - IDirect3DDevice9_CreateTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->miplevels, d3dusage, d3dformat, d3dpool, (IDirect3DTexture9 **)&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; - 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 @@ -2284,52 +2186,28 @@ 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; switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: if (bytesperblock) { - qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, glt->glinternalformat, mipwidth, mipheight, 0, mipsize, mippixels);CHECKGLERROR + qglCompressedTexImage2D(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: -#ifdef SUPPORTD3D - { - D3DLOCKED_RECT d3dlockedrect; - if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits) - { - memcpy(d3dlockedrect.pBits, mippixels, mipsize); - IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip); - } - break; - } -#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; - 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; } + if(upload_mippixels != mippixels) + Mem_Free(upload_mippixels); mippixels += mipsize; if (mipwidth <= 1 && mipheight <= 1) { @@ -2345,68 +2223,18 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen // after upload we have to set some parameters... switch(vid.renderpath) { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_CGGL: + case RENDERPATH_GL32: + case RENDERPATH_GLES2: +#ifdef GL_TEXTURE_MAX_LEVEL 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 break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - glt->d3daddressw = 0; - if (glt->flags & TEXF_CLAMP) - { - glt->d3daddressu = D3DTADDRESS_CLAMP; - glt->d3daddressv = D3DTADDRESS_CLAMP; - if (glt->tiledepth > 1) - glt->d3daddressw = D3DTADDRESS_CLAMP; - } - else - { - glt->d3daddressu = D3DTADDRESS_WRAP; - glt->d3daddressv = D3DTADDRESS_WRAP; - if (glt->tiledepth > 1) - glt->d3daddressw = D3DTADDRESS_WRAP; - } - glt->d3dmipmaplodbias = 0; - glt->d3dmaxmiplevel = 0; - glt->d3dmaxmiplevelfilter = 0; - if (glt->flags & TEXF_MIPMAP) - { - glt->d3dminfilter = d3d_filter_mipmin; - glt->d3dmagfilter = d3d_filter_mipmag; - glt->d3dmipfilter = d3d_filter_mipmix; - } - else - { - glt->d3dminfilter = d3d_filter_flatmin; - glt->d3dmagfilter = d3d_filter_flatmag; - glt->d3dmipfilter = d3d_filter_flatmix; - } -#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; - 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); @@ -2425,14 +2253,19 @@ int R_TextureHeight(rtexture_t *rt) return rt ? ((gltexture_t *)rt)->inputheight : 0; } -void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int width, int height) +int R_TextureFlags(rtexture_t *rt) +{ + return rt ? ((gltexture_t *)rt)->flags : 0; +} + +void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int z, int width, int height, int depth) { gltexture_t *glt = (gltexture_t *)rt; if (data == NULL) Host_Error("R_UpdateTexture: no data supplied"); if (glt == NULL) Host_Error("R_UpdateTexture: no texture supplied"); - if (!glt->texnum && !glt->d3dtexture) + if (!glt->texnum) { Con_DPrintf("R_UpdateTexture: texture %p \"%s\" in pool %p has not been uploaded yet\n", (void *)glt, glt->identifier, (void *)glt->pool); return; @@ -2446,6 +2279,8 @@ void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, in int outputskip = glt->tilewidth*bpp; const unsigned char *input = data; unsigned char *output = glt->bufferpixels; + if (glt->inputdepth != 1 || glt->sides != 1) + Sys_Error("R_UpdateTexture on buffered texture that is not 2D\n"); if (x < 0) { width += x; @@ -2470,8 +2305,8 @@ void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, in for (j = 0;j < height;j++, output += outputskip, input += inputskip) memcpy(output, input, width*bpp); } - else if (x || y || width != glt->inputwidth || height != glt->inputheight) - R_UploadPartialTexture(glt, data, x, y, 0, width, height, 1); + else if (x || y || z || width != glt->inputwidth || height != glt->inputheight || depth != glt->inputdepth) + R_UploadPartialTexture(glt, data, x, y, z, width, height, depth); else R_UploadFullTexture(glt, data); } @@ -2493,7 +2328,7 @@ int R_RealGetTexture(rtexture_t *rt) return glt->texnum; } else - return 0; + return r_texture_white->texnum; } void R_ClearTexture (rtexture_t *rt)