5 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
10 #include "intoverflow.h"
11 #include "dpsoftrast.h"
14 #define GL_TEXTURE_3D 0x806F
17 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)"};
18 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)"};
19 cvar_t gl_picmip = {CVAR_SAVE, "gl_picmip", "0", "reduces resolution of textures by powers of 2, for example 1 will halve width/height, reducing texture memory usage by 75%"};
20 cvar_t gl_picmip_world = {CVAR_SAVE, "gl_picmip_world", "0", "extra picmip level for world textures (may be negative, which will then reduce gl_picmip for these)"};
21 cvar_t r_picmipworld = {CVAR_SAVE, "r_picmipworld", "1", "whether gl_picmip shall apply to world textures too (setting this to 0 is a shorthand for gl_picmip_world -9999999)"};
22 cvar_t gl_picmip_sprites = {CVAR_SAVE, "gl_picmip_sprites", "0", "extra picmip level for sprite textures (may be negative, which will then reduce gl_picmip for these)"};
23 cvar_t r_picmipsprites = {CVAR_SAVE, "r_picmipsprites", "1", "make gl_picmip affect sprites too (saves some graphics memory in sprite heavy games) (setting this to 0 is a shorthand for gl_picmip_sprites -9999999)"};
24 cvar_t gl_picmip_other = {CVAR_SAVE, "gl_picmip_other", "0", "extra picmip level for other textures (may be negative, which will then reduce gl_picmip for these)"};
25 cvar_t r_lerpimages = {CVAR_SAVE, "r_lerpimages", "1", "bilinear filters images when scaling them up to power of 2 size (mode 1), looks better than glquake (mode 0)"};
26 cvar_t gl_texture_anisotropy = {CVAR_SAVE, "gl_texture_anisotropy", "1", "anisotropic filtering quality (if supported by hardware), 1 sample (no anisotropy) and 8 sample (8 tap anisotropy) are recommended values"};
27 cvar_t gl_texturecompression = {CVAR_SAVE, "gl_texturecompression", "0", "whether to compress textures, a value of 0 disables compression (even if the individual cvars are 1), 1 enables fast (low quality) compression at startup, 2 enables slow (high quality) compression at startup"};
28 cvar_t gl_texturecompression_color = {CVAR_SAVE, "gl_texturecompression_color", "1", "whether to compress colormap (diffuse) textures"};
29 cvar_t gl_texturecompression_normal = {CVAR_SAVE, "gl_texturecompression_normal", "0", "whether to compress normalmap (normalmap) textures"};
30 cvar_t gl_texturecompression_gloss = {CVAR_SAVE, "gl_texturecompression_gloss", "1", "whether to compress glossmap (specular) textures"};
31 cvar_t gl_texturecompression_glow = {CVAR_SAVE, "gl_texturecompression_glow", "1", "whether to compress glowmap (luma) textures"};
32 cvar_t gl_texturecompression_2d = {CVAR_SAVE, "gl_texturecompression_2d", "0", "whether to compress 2d (hud/menu) textures other than the font"};
33 cvar_t gl_texturecompression_q3bsplightmaps = {CVAR_SAVE, "gl_texturecompression_q3bsplightmaps", "0", "whether to compress lightmaps in q3bsp format levels"};
34 cvar_t gl_texturecompression_q3bspdeluxemaps = {CVAR_SAVE, "gl_texturecompression_q3bspdeluxemaps", "0", "whether to compress deluxemaps in q3bsp format levels (only levels compiled with q3map2 -deluxe have these)"};
35 cvar_t gl_texturecompression_sky = {CVAR_SAVE, "gl_texturecompression_sky", "0", "whether to compress sky textures"};
36 cvar_t gl_texturecompression_lightcubemaps = {CVAR_SAVE, "gl_texturecompression_lightcubemaps", "1", "whether to compress light cubemaps (spotlights and other light projection images)"};
37 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)"};
38 cvar_t gl_texturecompression_sprites = {CVAR_SAVE, "gl_texturecompression_sprites", "1", "whether to compress sprites"};
39 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"};
40 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"};
41 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"};
42 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"};
44 qboolean gl_filter_force = false;
45 int gl_filter_min = GL_LINEAR_MIPMAP_LINEAR;
46 int gl_filter_mag = GL_LINEAR;
47 DPSOFTRAST_TEXTURE_FILTER dpsoftrast_filter_mipmap = DPSOFTRAST_TEXTURE_FILTER_LINEAR_MIPMAP_TRIANGLE;
48 DPSOFTRAST_TEXTURE_FILTER dpsoftrast_filter_nomipmap = DPSOFTRAST_TEXTURE_FILTER_LINEAR;
51 int d3d_filter_flatmin = D3DTEXF_LINEAR;
52 int d3d_filter_flatmag = D3DTEXF_LINEAR;
53 int d3d_filter_flatmix = D3DTEXF_POINT;
54 int d3d_filter_mipmin = D3DTEXF_LINEAR;
55 int d3d_filter_mipmag = D3DTEXF_LINEAR;
56 int d3d_filter_mipmix = D3DTEXF_LINEAR;
57 int d3d_filter_nomip = false;
61 static mempool_t *texturemempool;
62 static memexpandablearray_t texturearray;
64 // note: this must not conflict with TEXF_ flags in r_textures.h
65 // bitmask for mismatch checking
66 #define GLTEXF_IMPORTANTBITS (0)
67 // dynamic texture (treat texnum == 0 differently)
68 #define GLTEXF_DYNAMIC 0x00080000
70 typedef struct textypeinfo_s
74 int inputbytesperpixel;
75 int internalbytesperpixel;
76 float glinternalbytesperpixel;
85 // we use these internally even if we never deliver such data to the driver
87 #define GL_BGRA 0x80E1
89 // framebuffer texture formats
90 // GLES2 devices rarely support depth textures, so we actually use a renderbuffer there
91 static textypeinfo_t textype_shadowmap16_comp = {"shadowmap16_comp", TEXTYPE_SHADOWMAP16_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
92 static textypeinfo_t textype_shadowmap16_raw = {"shadowmap16_raw", TEXTYPE_SHADOWMAP16_RAW , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
93 static textypeinfo_t textype_shadowmap24_comp = {"shadowmap24_comp", TEXTYPE_SHADOWMAP24_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
94 static textypeinfo_t textype_shadowmap24_raw = {"shadowmap24_raw", TEXTYPE_SHADOWMAP24_RAW , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
95 static textypeinfo_t textype_depth16 = {"depth16", TEXTYPE_DEPTHBUFFER16 , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
96 static textypeinfo_t textype_depth24 = {"depth24", TEXTYPE_DEPTHBUFFER24 , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
97 static textypeinfo_t textype_depth24stencil8 = {"depth24stencil8", TEXTYPE_DEPTHBUFFER24STENCIL8, 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
98 static textypeinfo_t textype_colorbuffer = {"colorbuffer", TEXTYPE_COLORBUFFER , 2, 2, 2.0f, GL_RGB565 , GL_RGBA , GL_UNSIGNED_SHORT_5_6_5};
99 static textypeinfo_t textype_colorbuffer16f = {"colorbuffer16f", TEXTYPE_COLORBUFFER16F , 2, 2, 2.0f, GL_RGB565 , GL_RGBA , GL_UNSIGNED_SHORT_5_6_5};
100 static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F , 2, 2, 2.0f, GL_RGB565 , GL_RGBA , GL_UNSIGNED_SHORT_5_6_5};
103 static textypeinfo_t textype_alpha = {"alpha", TEXTYPE_ALPHA , 1, 4, 4.0f, GL_ALPHA , GL_ALPHA , GL_UNSIGNED_BYTE };
104 static textypeinfo_t textype_palette = {"palette", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
105 static textypeinfo_t textype_palette_alpha = {"palette_alpha", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
106 static textypeinfo_t textype_rgba = {"rgba", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE };
107 static textypeinfo_t textype_rgba_alpha = {"rgba_alpha", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE };
108 static textypeinfo_t textype_bgra = {"bgra", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
109 static textypeinfo_t textype_bgra_alpha = {"bgra_alpha", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
111 static textypeinfo_t textype_etc1 = {"etc1", TEXTYPE_ETC1 , 1, 3, 0.5f, GL_ETC1_RGB8_OES , 0 , 0 };
114 // framebuffer texture formats
115 static textypeinfo_t textype_shadowmap16_comp = {"shadowmap16_comp", TEXTYPE_SHADOWMAP16_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
116 static textypeinfo_t textype_shadowmap16_raw = {"shadowmap16_raw", TEXTYPE_SHADOWMAP16_RAW , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
117 static textypeinfo_t textype_shadowmap24_comp = {"shadowmap24_comp", TEXTYPE_SHADOWMAP24_COMP , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT };
118 static textypeinfo_t textype_shadowmap24_raw = {"shadowmap24_raw", TEXTYPE_SHADOWMAP24_RAW , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT };
119 static textypeinfo_t textype_depth16 = {"depth16", TEXTYPE_DEPTHBUFFER16 , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
120 static textypeinfo_t textype_depth24 = {"depth24", TEXTYPE_DEPTHBUFFER24 , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT };
121 static textypeinfo_t textype_depth24stencil8 = {"depth24stencil8", TEXTYPE_DEPTHBUFFER24STENCIL8, 4, 4, 4.0f, GL_DEPTH24_STENCIL8_EXT , GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT};
122 static textypeinfo_t textype_colorbuffer = {"colorbuffer", TEXTYPE_COLORBUFFER , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
123 static textypeinfo_t textype_colorbuffer16f = {"colorbuffer16f", TEXTYPE_COLORBUFFER16F , 8, 8, 8.0f, GL_RGBA16F_ARB , GL_RGBA , GL_FLOAT };
124 static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F , 16, 16, 16.0f, GL_RGBA32F_ARB , GL_RGBA , GL_FLOAT };
127 static textypeinfo_t textype_alpha = {"alpha", TEXTYPE_ALPHA , 1, 4, 4.0f, GL_ALPHA , GL_ALPHA , GL_UNSIGNED_BYTE };
128 static textypeinfo_t textype_palette = {"palette", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGB , GL_BGRA , GL_UNSIGNED_BYTE };
129 static textypeinfo_t textype_palette_alpha = {"palette_alpha", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
130 static textypeinfo_t textype_rgba = {"rgba", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGB , GL_RGBA , GL_UNSIGNED_BYTE };
131 static textypeinfo_t textype_rgba_alpha = {"rgba_alpha", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE };
132 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 };
133 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 };
134 static textypeinfo_t textype_bgra = {"bgra", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGB , GL_BGRA , GL_UNSIGNED_BYTE };
135 static textypeinfo_t textype_bgra_alpha = {"bgra_alpha", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
136 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 };
137 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 };
138 static textypeinfo_t textype_dxt1 = {"dxt1", TEXTYPE_DXT1 , 4, 0, 0.5f, GL_COMPRESSED_RGB_S3TC_DXT1_EXT , 0 , 0 };
139 static textypeinfo_t textype_dxt1a = {"dxt1a", TEXTYPE_DXT1A , 4, 0, 0.5f, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT , 0 , 0 };
140 static textypeinfo_t textype_dxt3 = {"dxt3", TEXTYPE_DXT3 , 4, 0, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT , 0 , 0 };
141 static textypeinfo_t textype_dxt5 = {"dxt5", TEXTYPE_DXT5 , 4, 0, 1.0f, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT , 0 , 0 };
142 static textypeinfo_t textype_sRGB_palette = {"sRGB_palette", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_SRGB_EXT , GL_BGRA , GL_UNSIGNED_BYTE };
143 static textypeinfo_t textype_sRGB_palette_alpha = {"sRGB_palette_alpha", TEXTYPE_PALETTE , 1, 4, 4.0f, GL_SRGB_ALPHA_EXT , GL_BGRA , GL_UNSIGNED_BYTE };
144 static textypeinfo_t textype_sRGB_rgba = {"sRGB_rgba", TEXTYPE_RGBA , 4, 4, 4.0f, GL_SRGB_EXT , GL_RGBA , GL_UNSIGNED_BYTE };
145 static textypeinfo_t textype_sRGB_rgba_alpha = {"sRGB_rgba_alpha", TEXTYPE_RGBA , 4, 4, 4.0f, GL_SRGB_ALPHA_EXT , GL_RGBA , GL_UNSIGNED_BYTE };
146 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 };
147 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 };
148 static textypeinfo_t textype_sRGB_bgra = {"sRGB_bgra", TEXTYPE_BGRA , 4, 4, 4.0f, GL_SRGB_EXT , GL_BGRA , GL_UNSIGNED_BYTE };
149 static textypeinfo_t textype_sRGB_bgra_alpha = {"sRGB_bgra_alpha", TEXTYPE_BGRA , 4, 4, 4.0f, GL_SRGB_ALPHA_EXT , GL_BGRA , GL_UNSIGNED_BYTE };
150 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 };
151 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 };
152 static textypeinfo_t textype_sRGB_dxt1 = {"sRGB_dxt1", TEXTYPE_DXT1 , 4, 0, 0.5f, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT , 0 , 0 };
153 static textypeinfo_t textype_sRGB_dxt1a = {"sRGB_dxt1a", TEXTYPE_DXT1A , 4, 0, 0.5f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0 , 0 };
154 static textypeinfo_t textype_sRGB_dxt3 = {"sRGB_dxt3", TEXTYPE_DXT3 , 4, 0, 1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0 , 0 };
155 static textypeinfo_t textype_sRGB_dxt5 = {"sRGB_dxt5", TEXTYPE_DXT5 , 4, 0, 1.0f, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0 , 0 };
158 typedef enum gltexturetype_e
162 GLTEXTURETYPE_CUBEMAP,
167 static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP};
168 #ifdef GL_TEXTURE_WRAP_R
169 static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2};
171 static int cubemapside[6] =
173 GL_TEXTURE_CUBE_MAP_POSITIVE_X,
174 GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
175 GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
176 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
177 GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
178 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
181 typedef struct gltexture_s
183 // this portion of the struct is exposed to the R_GetTexture macro for
184 // speed reasons, must be identical in rtexture_t!
185 int texnum; // GL texture slot number
186 int renderbuffernum; // GL renderbuffer slot number
187 qboolean dirty; // indicates that R_RealGetTexture should be called
188 qboolean glisdepthstencil; // indicates that FBO attachment has to be GL_DEPTH_STENCIL_ATTACHMENT
189 int gltexturetypeenum; // used by R_Mesh_TexBind
190 // d3d stuff the backend needs
194 qboolean d3disrendertargetsurface;
195 qboolean d3disdepthstencilsurface;
205 int d3dmaxmiplevelfilter;
206 int d3dmipmaplodbias;
210 // dynamic texture stuff [11/22/2007 Black]
211 updatecallback_t updatecallback;
212 void *updatacallback_data;
213 // --- [11/22/2007 Black]
215 // stores backup copy of texture for deferred texture updates (gl_nopartialtextureupdates cvar)
216 unsigned char *bufferpixels;
217 qboolean buffermodified;
219 // pointer to texturepool (check this to see if the texture is allocated)
220 struct gltexturepool_s *pool;
221 // pointer to next texture in texturepool chain
222 struct gltexture_s *chain;
223 // name of the texture (this might be removed someday), no duplicates
224 char identifier[MAX_QPATH + 32];
225 // original data size in *inputtexels
226 int inputwidth, inputheight, inputdepth;
227 // copy of the original texture(s) supplied to the upload function, for
228 // delayed uploads (non-precached)
229 unsigned char *inputtexels;
230 // original data size in *inputtexels
232 // flags supplied to the LoadTexture function
233 // (might be altered to remove TEXF_ALPHA), and GLTEXF_ private flags
237 // pointer to one of the textype_ structs
238 textypeinfo_t *textype;
239 // one of the GLTEXTURETYPE_ values
241 // palette if the texture is TEXTYPE_PALETTE
242 const unsigned int *palette;
243 // actual stored texture size after gl_picmip and gl_max_size are applied
244 // (power of 2 if vid.support.arb_texture_non_power_of_two is not supported)
245 int tilewidth, tileheight, tiledepth;
246 // 1 or 6 depending on texturetype
248 // how many mipmap levels in this texture
252 // GL_RGB or GL_RGBA or GL_DEPTH_COMPONENT
255 int glinternalformat;
256 // GL_UNSIGNED_BYTE or GL_UNSIGNED_INT or GL_UNSIGNED_SHORT or GL_FLOAT
261 #define TEXTUREPOOL_SENTINEL 0xC0DEDBAD
263 typedef struct gltexturepool_s
265 unsigned int sentinel;
266 struct gltexture_s *gltchain;
267 struct gltexturepool_s *next;
271 static gltexturepool_t *gltexturepoolchain = NULL;
273 static unsigned char *resizebuffer = NULL, *colorconvertbuffer;
274 static int resizebuffersize = 0;
275 static const unsigned char *texturebuffer;
277 static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags)
282 case TEXTYPE_PALETTE: return (flags & TEXF_ALPHA) ? &textype_palette_alpha : &textype_palette;
283 case TEXTYPE_RGBA: return ((flags & TEXF_ALPHA) ? &textype_rgba_alpha : &textype_rgba);
284 case TEXTYPE_BGRA: return ((flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra);
286 case TEXTYPE_ETC1: return &textype_etc1;
288 case TEXTYPE_ALPHA: return &textype_alpha;
289 case TEXTYPE_COLORBUFFER: return &textype_colorbuffer;
290 case TEXTYPE_COLORBUFFER16F: return &textype_colorbuffer16f;
291 case TEXTYPE_COLORBUFFER32F: return &textype_colorbuffer32f;
292 case TEXTYPE_DEPTHBUFFER16: return &textype_depth16;
293 case TEXTYPE_DEPTHBUFFER24: return &textype_depth24;
294 case TEXTYPE_DEPTHBUFFER24STENCIL8: return &textype_depth24stencil8;
295 case TEXTYPE_SHADOWMAP16_COMP: return &textype_shadowmap16_comp;
296 case TEXTYPE_SHADOWMAP16_RAW: return &textype_shadowmap16_raw;
297 case TEXTYPE_SHADOWMAP24_COMP: return &textype_shadowmap24_comp;
298 case TEXTYPE_SHADOWMAP24_RAW: return &textype_shadowmap24_raw;
300 case TEXTYPE_DXT1: return &textype_dxt1;
301 case TEXTYPE_DXT1A: return &textype_dxt1a;
302 case TEXTYPE_DXT3: return &textype_dxt3;
303 case TEXTYPE_DXT5: return &textype_dxt5;
304 case TEXTYPE_PALETTE: return (flags & TEXF_ALPHA) ? &textype_palette_alpha : &textype_palette;
305 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);
306 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);
307 case TEXTYPE_ALPHA: return &textype_alpha;
308 case TEXTYPE_COLORBUFFER: return &textype_colorbuffer;
309 case TEXTYPE_COLORBUFFER16F: return &textype_colorbuffer16f;
310 case TEXTYPE_COLORBUFFER32F: return &textype_colorbuffer32f;
311 case TEXTYPE_DEPTHBUFFER16: return &textype_depth16;
312 case TEXTYPE_DEPTHBUFFER24: return &textype_depth24;
313 case TEXTYPE_DEPTHBUFFER24STENCIL8: return &textype_depth24stencil8;
314 case TEXTYPE_SHADOWMAP16_COMP: return &textype_shadowmap16_comp;
315 case TEXTYPE_SHADOWMAP16_RAW: return &textype_shadowmap16_raw;
316 case TEXTYPE_SHADOWMAP24_COMP: return &textype_shadowmap24_comp;
317 case TEXTYPE_SHADOWMAP24_RAW: return &textype_shadowmap24_raw;
318 case TEXTYPE_SRGB_DXT1: return &textype_sRGB_dxt1;
319 case TEXTYPE_SRGB_DXT1A: return &textype_sRGB_dxt1a;
320 case TEXTYPE_SRGB_DXT3: return &textype_sRGB_dxt3;
321 case TEXTYPE_SRGB_DXT5: return &textype_sRGB_dxt5;
322 case TEXTYPE_SRGB_PALETTE: return (flags & TEXF_ALPHA) ? &textype_sRGB_palette_alpha : &textype_sRGB_palette;
323 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);
324 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);
327 Host_Error("R_GetTexTypeInfo: unknown texture format");
333 // dynamic texture code [11/22/2007 Black]
334 void R_MarkDirtyTexture(rtexture_t *rt) {
335 gltexture_t *glt = (gltexture_t*) rt;
340 // dont do anything if the texture is already dirty (and make sure this *is* a dynamic texture after all!)
341 if (glt->flags & GLTEXF_DYNAMIC)
343 // mark it as dirty, so R_RealGetTexture gets called
348 void R_MakeTextureDynamic(rtexture_t *rt, updatecallback_t updatecallback, void *data) {
349 gltexture_t *glt = (gltexture_t*) rt;
354 glt->flags |= GLTEXF_DYNAMIC;
355 glt->updatecallback = updatecallback;
356 glt->updatacallback_data = data;
359 static void R_UpdateDynamicTexture(gltexture_t *glt) {
361 if( glt->updatecallback ) {
362 glt->updatecallback( (rtexture_t*) glt, glt->updatacallback_data );
366 void R_PurgeTexture(rtexture_t *rt)
368 if(rt && !(((gltexture_t*) rt)->flags & TEXF_PERSISTENT)) {
373 void R_FreeTexture(rtexture_t *rt)
375 gltexture_t *glt, **gltpointer;
377 glt = (gltexture_t *)rt;
379 Host_Error("R_FreeTexture: texture == NULL");
381 for (gltpointer = &glt->pool->gltchain;*gltpointer && *gltpointer != glt;gltpointer = &(*gltpointer)->chain);
382 if (*gltpointer == glt)
383 *gltpointer = glt->chain;
385 Host_Error("R_FreeTexture: texture \"%s\" not linked in pool", glt->identifier);
387 R_Mesh_ClearBindingsForTexture(glt->texnum);
389 switch(vid.renderpath)
391 case RENDERPATH_GL11:
392 case RENDERPATH_GL13:
393 case RENDERPATH_GL20:
394 case RENDERPATH_GLES1:
395 case RENDERPATH_GLES2:
399 qglDeleteTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
401 if (glt->renderbuffernum)
404 qglDeleteRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR
407 case RENDERPATH_D3D9:
410 IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dsurface);
411 else if (glt->tiledepth > 1)
412 IDirect3DVolumeTexture9_Release((IDirect3DVolumeTexture9 *)glt->d3dtexture);
413 else if (glt->sides == 6)
414 IDirect3DCubeTexture9_Release((IDirect3DCubeTexture9 *)glt->d3dtexture);
416 IDirect3DTexture9_Release((IDirect3DTexture9 *)glt->d3dtexture);
417 glt->d3dtexture = NULL;
418 glt->d3dsurface = NULL;
421 case RENDERPATH_D3D10:
422 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
424 case RENDERPATH_D3D11:
425 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
427 case RENDERPATH_SOFT:
429 DPSOFTRAST_Texture_Free(glt->texnum);
433 if (glt->inputtexels)
434 Mem_Free(glt->inputtexels);
435 Mem_ExpandableArray_FreeRecord(&texturearray, glt);
438 rtexturepool_t *R_AllocTexturePool(void)
440 gltexturepool_t *pool;
441 if (texturemempool == NULL)
443 pool = (gltexturepool_t *)Mem_Alloc(texturemempool, sizeof(gltexturepool_t));
446 pool->next = gltexturepoolchain;
447 gltexturepoolchain = pool;
448 pool->sentinel = TEXTUREPOOL_SENTINEL;
449 return (rtexturepool_t *)pool;
452 void R_FreeTexturePool(rtexturepool_t **rtexturepool)
454 gltexturepool_t *pool, **poolpointer;
455 if (rtexturepool == NULL)
457 if (*rtexturepool == NULL)
459 pool = (gltexturepool_t *)(*rtexturepool);
460 *rtexturepool = NULL;
461 if (pool->sentinel != TEXTUREPOOL_SENTINEL)
462 Host_Error("R_FreeTexturePool: pool already freed");
463 for (poolpointer = &gltexturepoolchain;*poolpointer && *poolpointer != pool;poolpointer = &(*poolpointer)->next);
464 if (*poolpointer == pool)
465 *poolpointer = pool->next;
467 Host_Error("R_FreeTexturePool: pool not linked");
468 while (pool->gltchain)
469 R_FreeTexture((rtexture_t *)pool->gltchain);
474 typedef struct glmode_s
477 int minification, magnification;
478 DPSOFTRAST_TEXTURE_FILTER dpsoftrastfilter_mipmap, dpsoftrastfilter_nomipmap;
482 static glmode_t modes[6] =
484 {"GL_NEAREST", GL_NEAREST, GL_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST},
485 {"GL_LINEAR", GL_LINEAR, GL_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR},
486 {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_NEAREST},
487 {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_LINEAR},
488 {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_NEAREST},
489 {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_LINEAR}
493 typedef struct d3dmode_s
500 static d3dmode_t d3dmodes[6] =
502 {"GL_NEAREST", D3DTEXF_POINT, D3DTEXF_POINT},
503 {"GL_LINEAR", D3DTEXF_LINEAR, D3DTEXF_POINT},
504 {"GL_NEAREST_MIPMAP_NEAREST", D3DTEXF_POINT, D3DTEXF_POINT},
505 {"GL_LINEAR_MIPMAP_NEAREST", D3DTEXF_LINEAR, D3DTEXF_POINT},
506 {"GL_NEAREST_MIPMAP_LINEAR", D3DTEXF_POINT, D3DTEXF_LINEAR},
507 {"GL_LINEAR_MIPMAP_LINEAR", D3DTEXF_LINEAR, D3DTEXF_LINEAR}
511 static void GL_TextureMode_f (void)
516 gltexturepool_t *pool;
520 Con_Printf("Texture mode is %sforced\n", gl_filter_force ? "" : "not ");
521 for (i = 0;i < 6;i++)
523 if (gl_filter_min == modes[i].minification)
525 Con_Printf("%s\n", modes[i].name);
529 Con_Print("current filter is unknown???\n");
533 for (i = 0;i < (int)(sizeof(modes)/sizeof(*modes));i++)
534 if (!strcasecmp (modes[i].name, Cmd_Argv(1) ) )
538 Con_Print("bad filter name\n");
542 gl_filter_min = modes[i].minification;
543 gl_filter_mag = modes[i].magnification;
544 gl_filter_force = ((Cmd_Argc() > 2) && !strcasecmp(Cmd_Argv(2), "force"));
546 dpsoftrast_filter_mipmap = modes[i].dpsoftrastfilter_mipmap;
547 dpsoftrast_filter_nomipmap = modes[i].dpsoftrastfilter_nomipmap;
549 switch(vid.renderpath)
551 case RENDERPATH_GL11:
552 case RENDERPATH_GL13:
553 case RENDERPATH_GL20:
554 case RENDERPATH_GLES1:
555 case RENDERPATH_GLES2:
556 // change all the existing mipmap texture objects
557 // FIXME: force renderer(/client/something?) restart instead?
560 for (pool = gltexturepoolchain;pool;pool = pool->next)
562 for (glt = pool->gltchain;glt;glt = glt->chain)
564 // only update already uploaded images
565 if (glt->texnum && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
567 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
568 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
569 if (glt->flags & TEXF_MIPMAP)
571 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_min);CHECKGLERROR
575 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_mag);CHECKGLERROR
577 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR
578 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
583 case RENDERPATH_D3D9:
585 d3d_filter_flatmin = d3dmodes[i].m1;
586 d3d_filter_flatmag = d3dmodes[i].m1;
587 d3d_filter_flatmix = D3DTEXF_POINT;
588 d3d_filter_mipmin = d3dmodes[i].m1;
589 d3d_filter_mipmag = d3dmodes[i].m1;
590 d3d_filter_mipmix = d3dmodes[i].m2;
591 d3d_filter_nomip = i < 2;
592 if (gl_texture_anisotropy.integer > 1 && i == 5)
593 d3d_filter_mipmin = d3d_filter_mipmag = D3DTEXF_ANISOTROPIC;
594 for (pool = gltexturepoolchain;pool;pool = pool->next)
596 for (glt = pool->gltchain;glt;glt = glt->chain)
598 // only update already uploaded images
599 if (glt->d3dtexture && !glt->d3dsurface && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
601 if (glt->flags & TEXF_MIPMAP)
603 glt->d3dminfilter = d3d_filter_mipmin;
604 glt->d3dmagfilter = d3d_filter_mipmag;
605 glt->d3dmipfilter = d3d_filter_mipmix;
606 glt->d3dmaxmiplevelfilter = 0;
610 glt->d3dminfilter = d3d_filter_flatmin;
611 glt->d3dmagfilter = d3d_filter_flatmag;
612 glt->d3dmipfilter = d3d_filter_flatmix;
613 glt->d3dmaxmiplevelfilter = 0;
620 case RENDERPATH_D3D10:
621 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
623 case RENDERPATH_D3D11:
624 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
626 case RENDERPATH_SOFT:
627 // change all the existing texture objects
628 for (pool = gltexturepoolchain;pool;pool = pool->next)
629 for (glt = pool->gltchain;glt;glt = glt->chain)
630 if (glt->texnum && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
631 DPSOFTRAST_Texture_Filter(glt->texnum, (glt->flags & TEXF_MIPMAP) ? dpsoftrast_filter_mipmap : dpsoftrast_filter_nomipmap);
636 static void GL_Texture_CalcImageSize(int texturetype, int flags, int miplevel, int inwidth, int inheight, int indepth, int *outwidth, int *outheight, int *outdepth, int *outmiplevels)
638 int picmip = 0, maxsize = 0, width2 = 1, height2 = 1, depth2 = 1, miplevels = 1;
643 case GLTEXTURETYPE_2D:
644 maxsize = vid.maxtexturesize_2d;
645 if (flags & TEXF_PICMIP)
647 maxsize = bound(1, gl_max_size.integer, maxsize);
651 case GLTEXTURETYPE_3D:
652 maxsize = vid.maxtexturesize_3d;
654 case GLTEXTURETYPE_CUBEMAP:
655 maxsize = vid.maxtexturesize_cubemap;
659 if (vid.support.arb_texture_non_power_of_two)
661 width2 = min(inwidth >> picmip, maxsize);
662 height2 = min(inheight >> picmip, maxsize);
663 depth2 = min(indepth >> picmip, maxsize);
667 for (width2 = 1;width2 < inwidth;width2 <<= 1);
668 for (width2 >>= picmip;width2 > maxsize;width2 >>= 1);
669 for (height2 = 1;height2 < inheight;height2 <<= 1);
670 for (height2 >>= picmip;height2 > maxsize;height2 >>= 1);
671 for (depth2 = 1;depth2 < indepth;depth2 <<= 1);
672 for (depth2 >>= picmip;depth2 > maxsize;depth2 >>= 1);
675 switch(vid.renderpath)
677 case RENDERPATH_GL11:
678 case RENDERPATH_GL13:
679 case RENDERPATH_GL20:
680 case RENDERPATH_D3D10:
681 case RENDERPATH_D3D11:
682 case RENDERPATH_SOFT:
683 case RENDERPATH_GLES1:
684 case RENDERPATH_GLES2:
686 case RENDERPATH_D3D9:
688 // for some reason the REF rasterizer (and hence the PIX debugger) does not like small textures...
689 if (texturetype == GLTEXTURETYPE_2D)
691 width2 = max(width2, 2);
692 height2 = max(height2, 2);
699 if (flags & TEXF_MIPMAP)
701 int extent = max(width2, max(height2, depth2));
707 *outwidth = max(1, width2);
709 *outheight = max(1, height2);
711 *outdepth = max(1, depth2);
713 *outmiplevels = miplevels;
717 static int R_CalcTexelDataSize (gltexture_t *glt)
719 int width2, height2, depth2, size;
721 GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &width2, &height2, &depth2, NULL);
723 size = width2 * height2 * depth2;
725 if (glt->flags & TEXF_MIPMAP)
727 while (width2 > 1 || height2 > 1 || depth2 > 1)
735 size += width2 * height2 * depth2;
739 return (int)(size * glt->textype->glinternalbytesperpixel) * glt->sides;
742 void R_TextureStats_Print(qboolean printeach, qboolean printpool, qboolean printtotal)
746 int pooltotal = 0, pooltotalt = 0, pooltotalp = 0, poolloaded = 0, poolloadedt = 0, poolloadedp = 0;
747 int sumtotal = 0, sumtotalt = 0, sumtotalp = 0, sumloaded = 0, sumloadedt = 0, sumloadedp = 0;
749 gltexturepool_t *pool;
751 Con_Print("glsize input loaded mip alpha name\n");
752 for (pool = gltexturepoolchain;pool;pool = pool->next)
760 for (glt = pool->gltchain;glt;glt = glt->chain)
762 glsize = R_CalcTexelDataSize(glt);
763 isloaded = glt->texnum != 0 || glt->renderbuffernum != 0 || glt->d3dtexture || glt->d3dsurface;
765 pooltotalt += glsize;
766 pooltotalp += glt->inputdatasize;
770 poolloadedt += glsize;
771 poolloadedp += glt->inputdatasize;
774 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);
777 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);
778 sumtotal += pooltotal;
779 sumtotalt += pooltotalt;
780 sumtotalp += pooltotalp;
781 sumloaded += poolloaded;
782 sumloadedt += poolloadedt;
783 sumloadedp += poolloadedp;
786 Con_Printf("textures total: %i (%.3fMB, %.3fMB original), uploaded %i (%.3fMB, %.3fMB original), upload on demand %i (%.3fMB, %.3fMB original)\n", sumtotal, sumtotalt / 1048576.0, sumtotalp / 1048576.0, sumloaded, sumloadedt / 1048576.0, sumloadedp / 1048576.0, sumtotal - sumloaded, (sumtotalt - sumloadedt) / 1048576.0, (sumtotalp - sumloadedp) / 1048576.0);
789 static void R_TextureStats_f(void)
791 R_TextureStats_Print(true, true, true);
794 static void r_textures_start(void)
796 switch(vid.renderpath)
798 case RENDERPATH_GL11:
799 case RENDERPATH_GL13:
800 case RENDERPATH_GL20:
801 case RENDERPATH_GLES1:
802 case RENDERPATH_GLES2:
803 // LordHavoc: allow any alignment
805 qglPixelStorei(GL_UNPACK_ALIGNMENT, 1);CHECKGLERROR
806 qglPixelStorei(GL_PACK_ALIGNMENT, 1);CHECKGLERROR
808 case RENDERPATH_D3D9:
810 case RENDERPATH_D3D10:
811 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
813 case RENDERPATH_D3D11:
814 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
816 case RENDERPATH_SOFT:
820 texturemempool = Mem_AllocPool("texture management", 0, NULL);
821 Mem_ExpandableArray_NewArray(&texturearray, texturemempool, sizeof(gltexture_t), 512);
823 // Disable JPEG screenshots if the DLL isn't loaded
824 if (! JPEG_OpenLibrary ())
825 Cvar_SetValueQuick (&scr_screenshot_jpeg, 0);
826 if (! PNG_OpenLibrary ())
827 Cvar_SetValueQuick (&scr_screenshot_png, 0);
830 static void r_textures_shutdown(void)
832 rtexturepool_t *temp;
834 JPEG_CloseLibrary ();
836 while(gltexturepoolchain)
838 temp = (rtexturepool_t *) gltexturepoolchain;
839 R_FreeTexturePool(&temp);
842 resizebuffersize = 0;
844 colorconvertbuffer = NULL;
845 texturebuffer = NULL;
846 Mem_ExpandableArray_FreeArray(&texturearray);
847 Mem_FreePool(&texturemempool);
850 static void r_textures_newmap(void)
854 static void r_textures_devicelost(void)
858 endindex = (int)Mem_ExpandableArray_IndexRange(&texturearray);
859 for (i = 0;i < endindex;i++)
861 glt = (gltexture_t *) Mem_ExpandableArray_RecordAtIndex(&texturearray, i);
862 if (!glt || !(glt->flags & TEXF_RENDERTARGET))
864 switch(vid.renderpath)
866 case RENDERPATH_GL11:
867 case RENDERPATH_GL13:
868 case RENDERPATH_GL20:
869 case RENDERPATH_GLES1:
870 case RENDERPATH_GLES2:
872 case RENDERPATH_D3D9:
875 IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dsurface);
876 else if (glt->tiledepth > 1)
877 IDirect3DVolumeTexture9_Release((IDirect3DVolumeTexture9 *)glt->d3dtexture);
878 else if (glt->sides == 6)
879 IDirect3DCubeTexture9_Release((IDirect3DCubeTexture9 *)glt->d3dtexture);
881 IDirect3DTexture9_Release((IDirect3DTexture9 *)glt->d3dtexture);
882 glt->d3dtexture = NULL;
883 glt->d3dsurface = NULL;
886 case RENDERPATH_D3D10:
887 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
889 case RENDERPATH_D3D11:
890 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
892 case RENDERPATH_SOFT:
898 static void r_textures_devicerestored(void)
902 endindex = (int)Mem_ExpandableArray_IndexRange(&texturearray);
903 for (i = 0;i < endindex;i++)
905 glt = (gltexture_t *) Mem_ExpandableArray_RecordAtIndex(&texturearray, i);
906 if (!glt || !(glt->flags & TEXF_RENDERTARGET))
908 switch(vid.renderpath)
910 case RENDERPATH_GL11:
911 case RENDERPATH_GL13:
912 case RENDERPATH_GL20:
913 case RENDERPATH_GLES1:
914 case RENDERPATH_GLES2:
916 case RENDERPATH_D3D9:
920 if (glt->d3disrendertargetsurface)
922 if (FAILED(d3dresult = IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
923 Sys_Error("IDirect3DDevice9_CreateRenderTarget failed!");
925 else if (glt->d3disdepthstencilsurface)
927 if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
928 Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
930 else if (glt->tiledepth > 1)
932 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)))
933 Sys_Error("IDirect3DDevice9_CreateVolumeTexture failed!");
935 else if (glt->sides == 6)
937 if (FAILED(d3dresult = IDirect3DDevice9_CreateCubeTexture(vid_d3d9dev, glt->tilewidth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DCubeTexture9 **)&glt->d3dtexture, NULL)))
938 Sys_Error("IDirect3DDevice9_CreateCubeTexture failed!");
942 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)))
943 Sys_Error("IDirect3DDevice9_CreateTexture failed!");
948 case RENDERPATH_D3D10:
949 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
951 case RENDERPATH_D3D11:
952 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
954 case RENDERPATH_SOFT:
961 void R_Textures_Init (void)
963 Cmd_AddCommand("gl_texturemode", &GL_TextureMode_f, "set texture filtering mode (GL_NEAREST, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, etc); an additional argument 'force' forces the texture mode even in cases where it may not be appropriate");
964 Cmd_AddCommand("r_texturestats", R_TextureStats_f, "print information about all loaded textures and some statistics");
965 Cvar_RegisterVariable (&gl_max_size);
966 Cvar_RegisterVariable (&gl_picmip);
967 Cvar_RegisterVariable (&gl_picmip_world);
968 Cvar_RegisterVariable (&r_picmipworld);
969 Cvar_RegisterVariable (&gl_picmip_sprites);
970 Cvar_RegisterVariable (&r_picmipsprites);
971 Cvar_RegisterVariable (&gl_picmip_other);
972 Cvar_RegisterVariable (&gl_max_lightmapsize);
973 Cvar_RegisterVariable (&r_lerpimages);
974 Cvar_RegisterVariable (&gl_texture_anisotropy);
975 Cvar_RegisterVariable (&gl_texturecompression);
976 Cvar_RegisterVariable (&gl_texturecompression_color);
977 Cvar_RegisterVariable (&gl_texturecompression_normal);
978 Cvar_RegisterVariable (&gl_texturecompression_gloss);
979 Cvar_RegisterVariable (&gl_texturecompression_glow);
980 Cvar_RegisterVariable (&gl_texturecompression_2d);
981 Cvar_RegisterVariable (&gl_texturecompression_q3bsplightmaps);
982 Cvar_RegisterVariable (&gl_texturecompression_q3bspdeluxemaps);
983 Cvar_RegisterVariable (&gl_texturecompression_sky);
984 Cvar_RegisterVariable (&gl_texturecompression_lightcubemaps);
985 Cvar_RegisterVariable (&gl_texturecompression_reflectmask);
986 Cvar_RegisterVariable (&gl_texturecompression_sprites);
987 Cvar_RegisterVariable (&gl_nopartialtextureupdates);
988 Cvar_RegisterVariable (&r_texture_dds_load_alphamode);
989 Cvar_RegisterVariable (&r_texture_dds_load_logfailure);
990 Cvar_RegisterVariable (&r_texture_dds_swdecode);
992 R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown, r_textures_newmap, r_textures_devicelost, r_textures_devicerestored);
995 void R_Textures_Frame (void)
997 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
998 static int old_aniso = 0;
1001 // could do procedural texture animation here, if we keep track of which
1002 // textures were accessed this frame...
1004 // free the resize buffers
1005 resizebuffersize = 0;
1008 Mem_Free(resizebuffer);
1009 resizebuffer = NULL;
1011 if (colorconvertbuffer)
1013 Mem_Free(colorconvertbuffer);
1014 colorconvertbuffer = NULL;
1017 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1018 if (old_aniso != gl_texture_anisotropy.integer)
1021 gltexturepool_t *pool;
1022 GLint oldbindtexnum;
1024 old_aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
1026 Cvar_SetValueQuick(&gl_texture_anisotropy, old_aniso);
1028 switch(vid.renderpath)
1030 case RENDERPATH_GL11:
1031 case RENDERPATH_GL13:
1032 case RENDERPATH_GL20:
1033 case RENDERPATH_GLES1:
1034 case RENDERPATH_GLES2:
1036 GL_ActiveTexture(0);
1037 for (pool = gltexturepoolchain;pool;pool = pool->next)
1039 for (glt = pool->gltchain;glt;glt = glt->chain)
1041 // only update already uploaded images
1042 if (glt->texnum && (glt->flags & TEXF_MIPMAP) == TEXF_MIPMAP)
1044 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
1046 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
1047 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_ANISOTROPY_EXT, old_aniso);CHECKGLERROR
1049 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
1054 case RENDERPATH_D3D9:
1055 case RENDERPATH_D3D10:
1056 case RENDERPATH_D3D11:
1057 case RENDERPATH_SOFT:
1064 static void R_MakeResizeBufferBigger(int size)
1066 if (resizebuffersize < size)
1068 resizebuffersize = size;
1070 Mem_Free(resizebuffer);
1071 if (colorconvertbuffer)
1072 Mem_Free(colorconvertbuffer);
1073 resizebuffer = (unsigned char *)Mem_Alloc(texturemempool, resizebuffersize);
1074 colorconvertbuffer = (unsigned char *)Mem_Alloc(texturemempool, resizebuffersize);
1075 if (!resizebuffer || !colorconvertbuffer)
1076 Host_Error("R_Upload: out of memory");
1080 static void GL_SetupTextureParameters(int flags, textype_t textype, int texturetype)
1082 int textureenum = gltexturetypeenums[texturetype];
1083 int wrapmode = (flags & TEXF_CLAMP) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
1087 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1088 if (vid.support.ext_texture_filter_anisotropic && (flags & TEXF_MIPMAP))
1090 int aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
1091 if (gl_texture_anisotropy.integer != aniso)
1092 Cvar_SetValueQuick(&gl_texture_anisotropy, aniso);
1093 qglTexParameteri(textureenum, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);CHECKGLERROR
1096 qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode);CHECKGLERROR
1097 qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode);CHECKGLERROR
1098 #ifdef GL_TEXTURE_WRAP_R
1099 if (gltexturetypedimensions[texturetype] >= 3)
1101 qglTexParameteri(textureenum, GL_TEXTURE_WRAP_R, wrapmode);CHECKGLERROR
1106 if (!gl_filter_force && flags & TEXF_FORCENEAREST)
1108 if (flags & TEXF_MIPMAP)
1110 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);CHECKGLERROR
1114 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_NEAREST);CHECKGLERROR
1116 qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, GL_NEAREST);CHECKGLERROR
1118 else if (!gl_filter_force && flags & TEXF_FORCELINEAR)
1120 if (flags & TEXF_MIPMAP)
1122 if (gl_filter_min == GL_NEAREST_MIPMAP_LINEAR || gl_filter_min == GL_LINEAR_MIPMAP_LINEAR)
1124 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);CHECKGLERROR
1128 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);CHECKGLERROR
1133 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_LINEAR);CHECKGLERROR
1135 qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, GL_LINEAR);CHECKGLERROR
1139 if (flags & TEXF_MIPMAP)
1141 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_min);CHECKGLERROR
1145 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_mag);CHECKGLERROR
1147 qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR
1150 #ifdef GL_TEXTURE_COMPARE_MODE_ARB
1153 case TEXTYPE_SHADOWMAP16_COMP:
1154 case TEXTYPE_SHADOWMAP24_COMP:
1155 qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
1156 qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
1157 qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
1159 case TEXTYPE_SHADOWMAP16_RAW:
1160 case TEXTYPE_SHADOWMAP24_RAW:
1161 qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
1162 qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
1163 qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
1173 static void R_UploadPartialTexture(gltexture_t *glt, const unsigned char *data, int fragx, int fragy, int fragz, int fragwidth, int fragheight, int fragdepth)
1176 Sys_Error("R_UploadPartialTexture \"%s\": partial update with NULL pixels", glt->identifier);
1178 if (glt->texturetype != GLTEXTURETYPE_2D)
1179 Sys_Error("R_UploadPartialTexture \"%s\": partial update of type other than 2D", glt->identifier);
1181 if (glt->textype->textype == TEXTYPE_PALETTE)
1182 Sys_Error("R_UploadPartialTexture \"%s\": partial update of paletted texture", glt->identifier);
1184 if (glt->flags & (TEXF_MIPMAP | TEXF_PICMIP))
1185 Sys_Error("R_UploadPartialTexture \"%s\": partial update not supported with MIPMAP or PICMIP flags", glt->identifier);
1187 if (glt->inputwidth != glt->tilewidth || glt->inputheight != glt->tileheight || glt->tiledepth != 1)
1188 Sys_Error("R_UploadPartialTexture \"%s\": partial update not supported with stretched or special textures", glt->identifier);
1190 // update a portion of the image
1192 switch(vid.renderpath)
1194 case RENDERPATH_GL11:
1195 case RENDERPATH_GL13:
1196 case RENDERPATH_GL20:
1197 case RENDERPATH_GLES1:
1198 case RENDERPATH_GLES2:
1202 // we need to restore the texture binding after finishing the upload
1203 GL_ActiveTexture(0);
1204 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
1205 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
1206 qglTexSubImage2D(GL_TEXTURE_2D, 0, fragx, fragy, fragwidth, fragheight, glt->glformat, glt->gltype, data);CHECKGLERROR
1207 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
1210 case RENDERPATH_D3D9:
1214 D3DLOCKED_RECT d3dlockedrect;
1216 memset(&d3drect, 0, sizeof(d3drect));
1217 d3drect.left = fragx;
1218 d3drect.top = fragy;
1219 d3drect.right = fragx+fragwidth;
1220 d3drect.bottom = fragy+fragheight;
1221 if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, 0, &d3dlockedrect, &d3drect, 0) == D3D_OK && d3dlockedrect.pBits)
1223 for (y = 0;y < fragheight;y++)
1224 memcpy((unsigned char *)d3dlockedrect.pBits + d3dlockedrect.Pitch * y, data + fragwidth*glt->bytesperpixel * y, fragwidth*glt->bytesperpixel);
1225 IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, 0);
1230 case RENDERPATH_D3D10:
1231 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1233 case RENDERPATH_D3D11:
1234 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1236 case RENDERPATH_SOFT:
1237 DPSOFTRAST_Texture_UpdatePartial(glt->texnum, 0, data, fragx, fragy, fragwidth, fragheight);
1242 static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data)
1244 int i, mip = 0, width, height, depth;
1245 GLint oldbindtexnum = 0;
1246 const unsigned char *prevbuffer;
1249 // error out if a stretch is needed on special texture types
1250 if (glt->texturetype != GLTEXTURETYPE_2D && (glt->tilewidth != glt->inputwidth || glt->tileheight != glt->inputheight || glt->tiledepth != glt->inputdepth))
1251 Sys_Error("R_UploadFullTexture \"%s\": stretch uploads allowed only on 2D textures\n", glt->identifier);
1253 // when picmip or maxsize is applied, we scale up to a power of 2 multiple
1254 // of the target size and then use the mipmap reduction function to get
1255 // high quality supersampled results
1256 for (width = glt->tilewidth;width < glt->inputwidth ;width <<= 1);
1257 for (height = glt->tileheight;height < glt->inputheight;height <<= 1);
1258 for (depth = glt->tiledepth;depth < glt->inputdepth ;depth <<= 1);
1259 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1261 if (prevbuffer == NULL)
1263 width = glt->tilewidth;
1264 height = glt->tileheight;
1265 depth = glt->tiledepth;
1266 // memset(resizebuffer, 0, width * height * depth * glt->sides * glt->bytesperpixel);
1267 // prevbuffer = resizebuffer;
1271 if (glt->textype->textype == TEXTYPE_PALETTE)
1273 // promote paletted to BGRA, so we only have to worry about BGRA in the rest of this code
1274 Image_Copy8bitBGRA(prevbuffer, colorconvertbuffer, glt->inputwidth * glt->inputheight * glt->inputdepth * glt->sides, glt->palette);
1275 prevbuffer = colorconvertbuffer;
1277 if (glt->flags & TEXF_RGBMULTIPLYBYALPHA)
1279 // multiply RGB channels by A channel before uploading
1281 for (i = 0;i < glt->inputwidth*glt->inputheight*glt->inputdepth*4;i += 4)
1283 alpha = prevbuffer[i+3];
1284 colorconvertbuffer[i] = (prevbuffer[i] * alpha) >> 8;
1285 colorconvertbuffer[i+1] = (prevbuffer[i+1] * alpha) >> 8;
1286 colorconvertbuffer[i+2] = (prevbuffer[i+2] * alpha) >> 8;
1287 colorconvertbuffer[i+3] = alpha;
1289 prevbuffer = colorconvertbuffer;
1291 // scale up to a power of 2 size (if appropriate)
1292 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1294 Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1295 prevbuffer = resizebuffer;
1297 // apply mipmap reduction algorithm to get down to picmip/max_size
1298 while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1300 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1301 prevbuffer = resizebuffer;
1305 // do the appropriate upload type...
1306 switch(vid.renderpath)
1308 case RENDERPATH_GL11:
1309 case RENDERPATH_GL13:
1310 case RENDERPATH_GL20:
1311 case RENDERPATH_GLES1:
1312 case RENDERPATH_GLES2:
1313 if (glt->texnum) // not renderbuffers
1317 // we need to restore the texture binding after finishing the upload
1318 GL_ActiveTexture(0);
1319 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
1320 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
1323 #ifdef GL_TEXTURE_COMPRESSION_HINT_ARB
1324 if (qglGetCompressedTexImageARB)
1326 if (gl_texturecompression.integer >= 2)
1327 qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
1329 qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_FASTEST);
1334 switch(glt->texturetype)
1336 case GLTEXTURETYPE_2D:
1337 qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1338 if (glt->flags & TEXF_MIPMAP)
1340 while (width > 1 || height > 1 || depth > 1)
1342 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1343 prevbuffer = resizebuffer;
1344 qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1348 case GLTEXTURETYPE_3D:
1350 qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1351 if (glt->flags & TEXF_MIPMAP)
1353 while (width > 1 || height > 1 || depth > 1)
1355 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1356 prevbuffer = resizebuffer;
1357 qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1362 case GLTEXTURETYPE_CUBEMAP:
1363 // convert and upload each side in turn,
1364 // from a continuous block of input texels
1365 texturebuffer = (unsigned char *)prevbuffer;
1366 for (i = 0;i < 6;i++)
1368 prevbuffer = texturebuffer;
1369 texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
1370 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1372 Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1373 prevbuffer = resizebuffer;
1376 while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1378 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1379 prevbuffer = resizebuffer;
1382 qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1383 if (glt->flags & TEXF_MIPMAP)
1385 while (width > 1 || height > 1 || depth > 1)
1387 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1388 prevbuffer = resizebuffer;
1389 qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1395 GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
1396 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
1399 case RENDERPATH_D3D9:
1401 if (!(glt->flags & TEXF_RENDERTARGET) && glt->d3dtexture && !glt->d3dsurface)
1403 D3DLOCKED_RECT d3dlockedrect;
1404 D3DLOCKED_BOX d3dlockedbox;
1405 switch(glt->texturetype)
1407 case GLTEXTURETYPE_2D:
1408 if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1411 memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1413 memset(d3dlockedrect.pBits, 255, width*height*glt->bytesperpixel);
1414 IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
1417 if ((glt->flags & TEXF_MIPMAP) && prevbuffer)
1419 while (width > 1 || height > 1 || depth > 1)
1421 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1422 prevbuffer = resizebuffer;
1423 if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1425 memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1426 IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
1432 case GLTEXTURETYPE_3D:
1433 if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits)
1435 // we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes
1436 memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel);
1437 IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip);
1440 if (glt->flags & TEXF_MIPMAP)
1442 while (width > 1 || height > 1 || depth > 1)
1444 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1445 prevbuffer = resizebuffer;
1446 if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits)
1448 // we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes
1449 memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel);
1450 IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip);
1456 case GLTEXTURETYPE_CUBEMAP:
1457 // convert and upload each side in turn,
1458 // from a continuous block of input texels
1459 texturebuffer = (unsigned char *)prevbuffer;
1460 for (i = 0;i < 6;i++)
1462 prevbuffer = texturebuffer;
1463 texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
1464 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1466 Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1467 prevbuffer = resizebuffer;
1470 while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1472 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1473 prevbuffer = resizebuffer;
1476 if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1478 memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1479 IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip);
1482 if (glt->flags & TEXF_MIPMAP)
1484 while (width > 1 || height > 1 || depth > 1)
1486 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1487 prevbuffer = resizebuffer;
1488 if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1490 memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1491 IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip);
1500 glt->d3daddressw = 0;
1501 if (glt->flags & TEXF_CLAMP)
1503 glt->d3daddressu = D3DTADDRESS_CLAMP;
1504 glt->d3daddressv = D3DTADDRESS_CLAMP;
1505 if (glt->tiledepth > 1)
1506 glt->d3daddressw = D3DTADDRESS_CLAMP;
1510 glt->d3daddressu = D3DTADDRESS_WRAP;
1511 glt->d3daddressv = D3DTADDRESS_WRAP;
1512 if (glt->tiledepth > 1)
1513 glt->d3daddressw = D3DTADDRESS_WRAP;
1515 glt->d3dmipmaplodbias = 0;
1516 glt->d3dmaxmiplevel = 0;
1517 glt->d3dmaxmiplevelfilter = d3d_filter_nomip ? 0 : glt->d3dmaxmiplevel;
1518 if (glt->flags & TEXF_FORCELINEAR)
1520 glt->d3dminfilter = D3DTEXF_LINEAR;
1521 glt->d3dmagfilter = D3DTEXF_LINEAR;
1522 glt->d3dmipfilter = D3DTEXF_POINT;
1524 else if (glt->flags & TEXF_FORCENEAREST)
1526 glt->d3dminfilter = D3DTEXF_POINT;
1527 glt->d3dmagfilter = D3DTEXF_POINT;
1528 glt->d3dmipfilter = D3DTEXF_POINT;
1530 else if (glt->flags & TEXF_MIPMAP)
1532 glt->d3dminfilter = d3d_filter_mipmin;
1533 glt->d3dmagfilter = d3d_filter_mipmag;
1534 glt->d3dmipfilter = d3d_filter_mipmix;
1538 glt->d3dminfilter = d3d_filter_flatmin;
1539 glt->d3dmagfilter = d3d_filter_flatmag;
1540 glt->d3dmipfilter = d3d_filter_flatmix;
1544 case RENDERPATH_D3D10:
1545 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1547 case RENDERPATH_D3D11:
1548 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1550 case RENDERPATH_SOFT:
1551 switch(glt->texturetype)
1553 case GLTEXTURETYPE_2D:
1554 DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
1556 case GLTEXTURETYPE_3D:
1557 DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
1559 case GLTEXTURETYPE_CUBEMAP:
1560 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1562 unsigned char *combinedbuffer = (unsigned char *)Mem_Alloc(tempmempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
1563 // convert and upload each side in turn,
1564 // from a continuous block of input texels
1565 // copy the results into combinedbuffer
1566 texturebuffer = (unsigned char *)prevbuffer;
1567 for (i = 0;i < 6;i++)
1569 prevbuffer = texturebuffer;
1570 texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
1571 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1573 Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1574 prevbuffer = resizebuffer;
1577 while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1579 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1580 prevbuffer = resizebuffer;
1582 memcpy(combinedbuffer + i*glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel, prevbuffer, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel);
1584 DPSOFTRAST_Texture_UpdateFull(glt->texnum, combinedbuffer);
1585 Mem_Free(combinedbuffer);
1588 DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
1591 if (glt->flags & TEXF_FORCELINEAR)
1592 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
1593 else if (glt->flags & TEXF_FORCENEAREST)
1594 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
1595 else if (glt->flags & TEXF_MIPMAP)
1596 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
1598 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
1603 static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, int sides, int flags, int miplevel, textype_t textype, int texturetype, const unsigned char *data, const unsigned int *palette)
1607 gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
1608 textypeinfo_t *texinfo, *texinfo2;
1609 unsigned char *temppixels = NULL;
1612 if (cls.state == ca_dedicated)
1615 // see if we need to swap red and blue (BGRA <-> RGBA conversion)
1616 if (textype == TEXTYPE_PALETTE && vid.forcetextype == TEXTYPE_RGBA)
1618 int numpixels = width * height * depth * sides;
1619 size = numpixels * 4;
1620 temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
1623 const unsigned char *p;
1624 unsigned char *o = temppixels;
1625 for (i = 0;i < numpixels;i++, o += 4)
1627 p = (const unsigned char *)palette + 4*data[i];
1635 textype = TEXTYPE_RGBA;
1640 case TEXTYPE_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_BGRA;} break;
1641 case TEXTYPE_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_RGBA;} break;
1642 case TEXTYPE_SRGB_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_SRGB_BGRA;} break;
1643 case TEXTYPE_SRGB_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_SRGB_RGBA;} break;
1649 static int rgbaswapindices[4] = {2, 1, 0, 3};
1650 size = width * height * depth * sides * 4;
1651 temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
1653 Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices);
1657 // if sRGB texture formats are not supported, convert input to linear and upload as normal types
1658 if (!vid.support.ext_texture_srgb)
1660 qboolean convertsRGB = false;
1663 case TEXTYPE_SRGB_DXT1: textype = TEXTYPE_DXT1 ;convertsRGB = true;break;
1664 case TEXTYPE_SRGB_DXT1A: textype = TEXTYPE_DXT1A ;convertsRGB = true;break;
1665 case TEXTYPE_SRGB_DXT3: textype = TEXTYPE_DXT3 ;convertsRGB = true;break;
1666 case TEXTYPE_SRGB_DXT5: textype = TEXTYPE_DXT5 ;convertsRGB = true;break;
1667 case TEXTYPE_SRGB_PALETTE: textype = TEXTYPE_PALETTE;/*convertsRGB = true;*/break;
1668 case TEXTYPE_SRGB_RGBA: textype = TEXTYPE_RGBA ;convertsRGB = true;break;
1669 case TEXTYPE_SRGB_BGRA: textype = TEXTYPE_BGRA ;convertsRGB = true;break;
1673 if (convertsRGB && data)
1675 size = width * height * depth * sides * 4;
1678 temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
1679 memcpy(temppixels, data, size);
1682 Image_MakeLinearColorsFromsRGB(temppixels, temppixels, width*height*depth*sides);
1686 if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map)
1688 Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n");
1691 if (texturetype == GLTEXTURETYPE_3D && !vid.support.ext_texture_3d)
1693 Con_Printf ("R_LoadTexture: 3d texture not supported by driver\n");
1697 texinfo = R_GetTexTypeInfo(textype, flags);
1698 size = width * height * depth * sides * texinfo->inputbytesperpixel;
1701 Con_Printf ("R_LoadTexture: bogus texture size (%dx%dx%dx%dbppx%dsides = %d bytes)\n", width, height, depth, texinfo->inputbytesperpixel * 8, sides, size);
1705 // clear the alpha flag if the texture has no transparent pixels
1708 case TEXTYPE_PALETTE:
1709 case TEXTYPE_SRGB_PALETTE:
1710 if (flags & TEXF_ALPHA)
1712 flags &= ~TEXF_ALPHA;
1715 for (i = 0;i < size;i++)
1717 if (((unsigned char *)&palette[data[i]])[3] < 255)
1719 flags |= TEXF_ALPHA;
1728 case TEXTYPE_SRGB_RGBA:
1729 case TEXTYPE_SRGB_BGRA:
1730 if (flags & TEXF_ALPHA)
1732 flags &= ~TEXF_ALPHA;
1735 for (i = 3;i < size;i += 4)
1739 flags |= TEXF_ALPHA;
1746 case TEXTYPE_SHADOWMAP16_COMP:
1747 case TEXTYPE_SHADOWMAP16_RAW:
1748 case TEXTYPE_SHADOWMAP24_COMP:
1749 case TEXTYPE_SHADOWMAP24_RAW:
1752 case TEXTYPE_SRGB_DXT1:
1755 case TEXTYPE_SRGB_DXT1A:
1757 case TEXTYPE_SRGB_DXT3:
1759 case TEXTYPE_SRGB_DXT5:
1760 flags |= TEXF_ALPHA;
1763 flags |= TEXF_ALPHA;
1765 case TEXTYPE_COLORBUFFER:
1766 case TEXTYPE_COLORBUFFER16F:
1767 case TEXTYPE_COLORBUFFER32F:
1768 flags |= TEXF_ALPHA;
1771 Sys_Error("R_LoadTexture: unknown texture type");
1774 texinfo2 = R_GetTexTypeInfo(textype, flags);
1775 if(size == width * height * depth * sides * texinfo->inputbytesperpixel)
1778 Con_Printf ("R_LoadTexture: input size changed after alpha fallback\n");
1780 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
1782 strlcpy (glt->identifier, identifier, sizeof(glt->identifier));
1784 glt->chain = pool->gltchain;
1785 pool->gltchain = glt;
1786 glt->inputwidth = width;
1787 glt->inputheight = height;
1788 glt->inputdepth = depth;
1790 glt->miplevel = (miplevel < 0) ? R_PicmipForFlags(flags) : miplevel; // note: if miplevel is -1, we know the texture is in original size and we can picmip it normally
1791 glt->textype = texinfo;
1792 glt->texturetype = texturetype;
1793 glt->inputdatasize = size;
1794 glt->palette = palette;
1795 glt->glinternalformat = texinfo->glinternalformat;
1796 glt->glformat = texinfo->glformat;
1797 glt->gltype = texinfo->gltype;
1798 glt->bytesperpixel = texinfo->internalbytesperpixel;
1799 glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
1802 glt->glisdepthstencil = false;
1803 glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
1804 // init the dynamic texture attributes, too [11/22/2007 Black]
1805 glt->updatecallback = NULL;
1806 glt->updatacallback_data = NULL;
1808 GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth, &glt->miplevels);
1810 // upload the texture
1811 // data may be NULL (blank texture for dynamic rendering)
1812 switch(vid.renderpath)
1814 case RENDERPATH_GL11:
1815 case RENDERPATH_GL13:
1816 case RENDERPATH_GL20:
1817 case RENDERPATH_GLES1:
1818 case RENDERPATH_GLES2:
1820 qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
1822 case RENDERPATH_D3D9:
1825 D3DFORMAT d3dformat;
1830 d3dpool = D3DPOOL_MANAGED;
1831 if (flags & TEXF_RENDERTARGET)
1833 d3dusage |= D3DUSAGE_RENDERTARGET;
1834 d3dpool = D3DPOOL_DEFAULT;
1838 case TEXTYPE_PALETTE: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
1839 case TEXTYPE_RGBA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8B8G8R8 : D3DFMT_X8B8G8R8;break;
1840 case TEXTYPE_BGRA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
1841 case TEXTYPE_COLORBUFFER: d3dformat = D3DFMT_A8R8G8B8;break;
1842 case TEXTYPE_COLORBUFFER16F: d3dformat = D3DFMT_A16B16G16R16F;break;
1843 case TEXTYPE_COLORBUFFER32F: d3dformat = D3DFMT_A32B32G32R32F;break;
1844 case TEXTYPE_ALPHA: d3dformat = D3DFMT_A8;break;
1845 default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTexture: unsupported texture type %i when picking D3DFMT", (int)textype);break;
1847 glt->d3dformat = d3dformat;
1848 glt->d3dusage = d3dusage;
1849 glt->d3dpool = d3dpool;
1850 glt->d3disrendertargetsurface = false;
1851 glt->d3disdepthstencilsurface = false;
1852 if (glt->tiledepth > 1)
1854 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)))
1855 Sys_Error("IDirect3DDevice9_CreateVolumeTexture failed!");
1857 else if (glt->sides == 6)
1859 if (FAILED(d3dresult = IDirect3DDevice9_CreateCubeTexture(vid_d3d9dev, glt->tilewidth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DCubeTexture9 **)&glt->d3dtexture, NULL)))
1860 Sys_Error("IDirect3DDevice9_CreateCubeTexture failed!");
1864 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)))
1865 Sys_Error("IDirect3DDevice9_CreateTexture failed!");
1870 case RENDERPATH_D3D10:
1871 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1873 case RENDERPATH_D3D11:
1874 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1876 case RENDERPATH_SOFT:
1881 case TEXTYPE_PALETTE: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
1882 case TEXTYPE_RGBA: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA8;break;
1883 case TEXTYPE_BGRA: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
1884 case TEXTYPE_COLORBUFFER: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
1885 case TEXTYPE_COLORBUFFER16F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA16F;break;
1886 case TEXTYPE_COLORBUFFER32F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA32F;break;
1887 case TEXTYPE_SHADOWMAP16_COMP:
1888 case TEXTYPE_SHADOWMAP16_RAW:
1889 case TEXTYPE_SHADOWMAP24_COMP:
1890 case TEXTYPE_SHADOWMAP24_RAW: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
1891 case TEXTYPE_DEPTHBUFFER16:
1892 case TEXTYPE_DEPTHBUFFER24:
1893 case TEXTYPE_DEPTHBUFFER24STENCIL8: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
1894 case TEXTYPE_ALPHA: tflags = DPSOFTRAST_TEXTURE_FORMAT_ALPHA8;break;
1895 default: Sys_Error("R_LoadTexture: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
1897 if (glt->miplevels > 1) tflags |= DPSOFTRAST_TEXTURE_FLAG_MIPMAP;
1898 if (flags & TEXF_ALPHA) tflags |= DPSOFTRAST_TEXTURE_FLAG_USEALPHA;
1899 if (glt->sides == 6) tflags |= DPSOFTRAST_TEXTURE_FLAG_CUBEMAP;
1900 if (glt->flags & TEXF_CLAMP) tflags |= DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;
1901 glt->texnum = DPSOFTRAST_Texture_New(tflags, glt->tilewidth, glt->tileheight, glt->tiledepth);
1906 R_UploadFullTexture(glt, data);
1907 if ((glt->flags & TEXF_ALLOWUPDATES) && gl_nopartialtextureupdates.integer)
1908 glt->bufferpixels = (unsigned char *)Mem_Alloc(texturemempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
1910 // free any temporary processing buffer we allocated...
1912 Mem_Free(temppixels);
1914 // texture converting and uploading can take a while, so make sure we're sending keepalives
1915 // FIXME: this causes rendering during R_Shadow_DrawLights
1916 // CL_KeepaliveMessage(false);
1918 return (rtexture_t *)glt;
1921 rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
1923 return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, miplevel, textype, GLTEXTURETYPE_2D, data, palette);
1926 rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
1928 return R_SetupTexture(rtexturepool, identifier, width, height, depth, 1, flags, miplevel, textype, GLTEXTURETYPE_3D, data, palette);
1931 rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *identifier, int width, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette)
1933 return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, miplevel, textype, GLTEXTURETYPE_CUBEMAP, data, palette);
1936 rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype, qboolean filter)
1938 return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_RENDERTARGET | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR : TEXF_FORCENEAREST), -1, textype, GLTEXTURETYPE_2D, NULL, NULL);
1941 rtexture_t *R_LoadTextureRenderBuffer(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype)
1944 gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
1945 textypeinfo_t *texinfo;
1947 if (cls.state == ca_dedicated)
1950 texinfo = R_GetTexTypeInfo(textype, TEXF_RENDERTARGET | TEXF_CLAMP);
1952 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
1954 strlcpy (glt->identifier, identifier, sizeof(glt->identifier));
1956 glt->chain = pool->gltchain;
1957 pool->gltchain = glt;
1958 glt->inputwidth = width;
1959 glt->inputheight = height;
1960 glt->inputdepth = 1;
1961 glt->flags = TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_FORCENEAREST;
1963 glt->textype = texinfo;
1964 glt->texturetype = textype;
1965 glt->inputdatasize = width*height*texinfo->internalbytesperpixel;
1966 glt->palette = NULL;
1967 glt->glinternalformat = texinfo->glinternalformat;
1968 glt->glformat = texinfo->glformat;
1969 glt->gltype = texinfo->gltype;
1970 glt->bytesperpixel = texinfo->internalbytesperpixel;
1971 glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
1974 glt->glisdepthstencil = textype == TEXTYPE_DEPTHBUFFER24STENCIL8;
1975 glt->gltexturetypeenum = GL_TEXTURE_2D;
1976 // init the dynamic texture attributes, too [11/22/2007 Black]
1977 glt->updatecallback = NULL;
1978 glt->updatacallback_data = NULL;
1980 GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth, &glt->miplevels);
1982 // upload the texture
1983 // data may be NULL (blank texture for dynamic rendering)
1984 switch(vid.renderpath)
1986 case RENDERPATH_GL11:
1987 case RENDERPATH_GL13:
1988 case RENDERPATH_GL20:
1989 case RENDERPATH_GLES1:
1990 case RENDERPATH_GLES2:
1992 qglGenRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR
1993 qglBindRenderbuffer(GL_RENDERBUFFER, glt->renderbuffernum);CHECKGLERROR
1994 qglRenderbufferStorage(GL_RENDERBUFFER, glt->glinternalformat, glt->tilewidth, glt->tileheight);CHECKGLERROR
1995 // 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
1996 qglBindRenderbuffer(GL_RENDERBUFFER, 0);CHECKGLERROR
1998 case RENDERPATH_D3D9:
2001 D3DFORMAT d3dformat;
2003 glt->d3disrendertargetsurface = false;
2004 glt->d3disdepthstencilsurface = false;
2007 case TEXTYPE_COLORBUFFER: d3dformat = D3DFMT_A8R8G8B8;glt->d3disrendertargetsurface = true;break;
2008 case TEXTYPE_COLORBUFFER16F: d3dformat = D3DFMT_A16B16G16R16F;glt->d3disrendertargetsurface = true;break;
2009 case TEXTYPE_COLORBUFFER32F: d3dformat = D3DFMT_A32B32G32R32F;glt->d3disrendertargetsurface = true;break;
2010 case TEXTYPE_DEPTHBUFFER16: d3dformat = D3DFMT_D16;glt->d3disdepthstencilsurface = true;break;
2011 case TEXTYPE_DEPTHBUFFER24: d3dformat = D3DFMT_D24X8;glt->d3disdepthstencilsurface = true;break;
2012 case TEXTYPE_DEPTHBUFFER24STENCIL8: d3dformat = D3DFMT_D24S8;glt->d3disdepthstencilsurface = true;break;
2013 default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTextureRenderbuffer: unsupported texture type %i when picking D3DFMT", (int)textype);break;
2015 glt->d3dformat = d3dformat;
2018 if (glt->d3disrendertargetsurface)
2020 if (FAILED(d3dresult = IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
2021 Sys_Error("IDirect3DDevice9_CreateRenderTarget failed!");
2023 else if (glt->d3disdepthstencilsurface)
2025 if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
2026 Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
2031 case RENDERPATH_D3D10:
2032 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2034 case RENDERPATH_D3D11:
2035 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2037 case RENDERPATH_SOFT:
2042 case TEXTYPE_COLORBUFFER: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8 | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2043 case TEXTYPE_COLORBUFFER16F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA16F | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2044 case TEXTYPE_COLORBUFFER32F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA32F | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2045 case TEXTYPE_DEPTHBUFFER16:
2046 case TEXTYPE_DEPTHBUFFER24:
2047 case TEXTYPE_DEPTHBUFFER24STENCIL8: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2048 default: Sys_Error("R_LoadTextureRenderbuffer: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
2050 glt->texnum = DPSOFTRAST_Texture_New(tflags, glt->tilewidth, glt->tileheight, glt->tiledepth);
2055 return (rtexture_t *)glt;
2058 int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha)
2061 return -1; // unsupported on this platform
2063 gltexture_t *glt = (gltexture_t *)rt;
2066 int bytesperpixel = 0;
2067 int bytesperblock = 0;
2069 int dds_format_flags;
2077 GLint internalformat;
2078 const char *ddsfourcc;
2080 return -1; // NULL pointer
2081 if (!strcmp(gl_version, "2.0.5885 WinXP Release"))
2082 return -2; // broken driver - crashes on reading internal format
2083 if (!qglGetTexLevelParameteriv)
2085 GL_ActiveTexture(0);
2086 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
2087 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
2088 qglGetTexLevelParameteriv(gltexturetypeenums[glt->texturetype], 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat);
2089 switch(internalformat)
2091 default: ddsfourcc = NULL;bytesperpixel = 4;break;
2092 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
2093 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: ddsfourcc = "DXT1";bytesperblock = 8;break;
2094 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: ddsfourcc = "DXT3";bytesperblock = 16;break;
2095 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: ddsfourcc = "DXT5";bytesperblock = 16;break;
2097 // if premultiplied alpha, say so in the DDS file
2098 if(glt->flags & TEXF_RGBMULTIPLYBYALPHA)
2100 switch(internalformat)
2102 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: ddsfourcc = "DXT2";break;
2103 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: ddsfourcc = "DXT4";break;
2106 if (!bytesperblock && skipuncompressed)
2107 return -3; // skipped
2108 memset(mipinfo, 0, sizeof(mipinfo));
2109 mipinfo[0][0] = glt->tilewidth;
2110 mipinfo[0][1] = glt->tileheight;
2112 if ((glt->flags & TEXF_MIPMAP) && !(glt->tilewidth == 1 && glt->tileheight == 1))
2114 for (mip = 1;mip < 16;mip++)
2116 mipinfo[mip][0] = mipinfo[mip-1][0] > 1 ? mipinfo[mip-1][0] >> 1 : 1;
2117 mipinfo[mip][1] = mipinfo[mip-1][1] > 1 ? mipinfo[mip-1][1] >> 1 : 1;
2118 if (mipinfo[mip][0] == 1 && mipinfo[mip][1] == 1)
2126 for (mip = 0;mip < mipmaps;mip++)
2128 mipinfo[mip][2] = bytesperblock ? ((mipinfo[mip][0]+3)/4)*((mipinfo[mip][1]+3)/4)*bytesperblock : mipinfo[mip][0]*mipinfo[mip][1]*bytesperpixel;
2129 mipinfo[mip][3] = ddssize;
2130 ddssize += mipinfo[mip][2];
2132 dds = (unsigned char *)Mem_Alloc(tempmempool, ddssize);
2135 dds_caps1 = 0x1000; // DDSCAPS_TEXTURE
2139 dds_flags = 0x81007; // DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_LINEARSIZE
2140 dds_format_flags = 0x4; // DDPF_FOURCC
2144 dds_flags = 0x100F; // DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH
2145 dds_format_flags = 0x40; // DDPF_RGB
2149 dds_flags |= 0x20000; // DDSD_MIPMAPCOUNT
2150 dds_caps1 |= 0x400008; // DDSCAPS_MIPMAP | DDSCAPS_COMPLEX
2153 dds_format_flags |= 0x1; // DDPF_ALPHAPIXELS
2154 memcpy(dds, "DDS ", 4);
2155 StoreLittleLong(dds+4, 124); // http://msdn.microsoft.com/en-us/library/bb943982%28v=vs.85%29.aspx says so
2156 StoreLittleLong(dds+8, dds_flags);
2157 StoreLittleLong(dds+12, mipinfo[0][1]); // height
2158 StoreLittleLong(dds+16, mipinfo[0][0]); // width
2159 StoreLittleLong(dds+24, 0); // depth
2160 StoreLittleLong(dds+28, mipmaps); // mipmaps
2161 StoreLittleLong(dds+76, 32); // format size
2162 StoreLittleLong(dds+80, dds_format_flags);
2163 StoreLittleLong(dds+108, dds_caps1);
2164 StoreLittleLong(dds+112, dds_caps2);
2167 StoreLittleLong(dds+20, mipinfo[0][2]); // linear size
2168 memcpy(dds+84, ddsfourcc, 4);
2169 for (mip = 0;mip < mipmaps;mip++)
2171 qglGetCompressedTexImageARB(gltexturetypeenums[glt->texturetype], mip, dds + mipinfo[mip][3]);CHECKGLERROR
2176 StoreLittleLong(dds+20, mipinfo[0][0]*bytesperpixel); // pitch
2177 StoreLittleLong(dds+88, bytesperpixel*8); // bits per pixel
2178 dds[94] = dds[97] = dds[100] = dds[107] = 255; // bgra byte order masks
2179 for (mip = 0;mip < mipmaps;mip++)
2181 qglGetTexImage(gltexturetypeenums[glt->texturetype], mip, GL_BGRA, GL_UNSIGNED_BYTE, dds + mipinfo[mip][3]);CHECKGLERROR
2184 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2185 ret = FS_WriteFile(filename, dds, ddssize);
2187 return ret ? ddssize : -5;
2192 #include "ktx10/include/ktx.h"
2195 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
2197 int i, size, dds_format_flags, dds_miplevels, dds_width, dds_height;
2200 int bytesperblock, bytesperpixel;
2203 gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
2204 textypeinfo_t *texinfo;
2205 int mip, mipwidth, mipheight, mipsize, mipsize_total;
2206 unsigned int c, r, g, b;
2207 GLint oldbindtexnum = 0;
2208 unsigned char *mippixels;
2209 unsigned char *mippixels_start;
2210 unsigned char *ddspixels;
2212 fs_offset_t ddsfilesize;
2213 unsigned int ddssize;
2214 qboolean force_swdecode, npothack;
2216 // ELUAN: FIXME: separate this code
2220 KTX_dimensions sizes;
2223 if (cls.state == ca_dedicated)
2227 // ELUAN: FIXME: separate this code
2228 if (vid.renderpath != RENDERPATH_GLES2)
2230 Con_DPrintf("KTX texture format is only supported on the GLES2 renderpath\n");
2234 // some textures are specified with extensions, so it becomes .tga.dds
2235 FS_StripExtension (filename, vabuf2, sizeof(vabuf2));
2236 FS_StripExtension (vabuf2, vabuf, sizeof(vabuf));
2237 FS_DefaultExtension (vabuf, ".ktx", sizeof(vabuf));
2238 strsize = strlen(vabuf);
2240 for (i = 0; i <= strsize - 4; i++) // copy null termination
2241 vabuf[i] = vabuf[i + 4];
2243 Con_DPrintf("Loading %s...\n", vabuf);
2244 dds = FS_LoadFile(vabuf, tempmempool, true, &ddsfilesize);
2245 ddssize = ddsfilesize;
2249 Con_DPrintf("Not found!\n");
2250 return NULL; // not found
2252 Con_DPrintf("Found!\n");
2254 if (flags & TEXF_ALPHA)
2256 Con_DPrintf("KTX texture with alpha not supported yet, disabling\n");
2257 flags &= ~TEXF_ALPHA;
2263 GLboolean isMipmapped;
2264 KTX_error_code ktxerror;
2266 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
2268 // texture uploading can take a while, so make sure we're sending keepalives
2269 CL_KeepaliveMessage(false);
2271 // create the texture object
2273 GL_ActiveTexture(0);
2274 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[GLTEXTURETYPE_2D]);
2275 qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
2276 qglBindTexture(gltexturetypeenums[GLTEXTURETYPE_2D], glt->texnum);CHECKGLERROR
2278 // upload the texture
2279 // we need to restore the texture binding after finishing the upload
2281 // NOTE: some drivers fail with ETC1 NPOT (only PowerVR?). This may make the driver crash later.
2282 ktxerror = ktxLoadTextureM(dds, ddssize, &glt->texnum, &target, &sizes, &isMipmapped, &glerror,
2283 0, NULL);// can't CHECKGLERROR, the lib catches it
2285 // FIXME: delete texture if we fail here
2286 if (target != GL_TEXTURE_2D)
2288 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2290 Con_DPrintf("%s target != GL_TEXTURE_2D, target == %x\n", vabuf, target);
2291 return NULL; // FIXME: delete the texture from memory
2294 if (KTX_SUCCESS == ktxerror)
2296 textype = TEXTYPE_ETC1;
2297 flags &= ~TEXF_COMPRESS; // don't let the textype be wrong
2299 // return whether this texture is transparent
2301 *hasalphaflag = (flags & TEXF_ALPHA) != 0;
2303 // TODO: apply gl_picmip
2306 // TODO: only load mipmaps if requested
2309 flags |= TEXF_MIPMAP;
2311 flags &= ~TEXF_MIPMAP;
2313 texinfo = R_GetTexTypeInfo(textype, flags);
2315 strlcpy (glt->identifier, vabuf, sizeof(glt->identifier));
2317 glt->chain = pool->gltchain;
2318 pool->gltchain = glt;
2319 glt->inputwidth = sizes.width;
2320 glt->inputheight = sizes.height;
2321 glt->inputdepth = 1;
2323 glt->textype = texinfo;
2324 glt->texturetype = GLTEXTURETYPE_2D;
2325 glt->inputdatasize = ddssize;
2326 glt->glinternalformat = texinfo->glinternalformat;
2327 glt->glformat = texinfo->glformat;
2328 glt->gltype = texinfo->gltype;
2329 glt->bytesperpixel = texinfo->internalbytesperpixel;
2331 glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
2332 glt->tilewidth = sizes.width;
2333 glt->tileheight = sizes.height;
2335 glt->miplevels = isMipmapped ? 1 : 0; // FIXME
2337 // after upload we have to set some parameters...
2338 #ifdef GL_TEXTURE_MAX_LEVEL
2340 if (dds_miplevels >= 1 && !mipcomplete)
2342 // need to set GL_TEXTURE_MAX_LEVEL
2343 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR
2347 GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
2349 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2351 return (rtexture_t *)glt;
2355 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2357 Con_DPrintf("KTX texture %s failed to load: %x\n", vabuf, ktxerror);
2363 dds = FS_LoadFile(filename, tempmempool, true, &ddsfilesize);
2364 ddssize = ddsfilesize;
2368 if (r_texture_dds_load_logfailure.integer && (r_texture_dds_load_logfailure.integer >= 2 || !optionaltexture))
2369 Log_Printf("ddstexturefailures.log", "%s\n", filename);
2370 return NULL; // not found
2373 if (ddsfilesize <= 128 || memcmp(dds, "DDS ", 4) || ddssize < (unsigned int)BuffLittleLong(dds+4) || BuffLittleLong(dds+76) != 32)
2376 Con_Printf("^1%s: not a DDS image\n", filename);
2380 //dds_flags = BuffLittleLong(dds+8);
2381 dds_format_flags = BuffLittleLong(dds+80);
2382 dds_miplevels = (BuffLittleLong(dds+108) & 0x400000) ? BuffLittleLong(dds+28) : 1;
2383 dds_width = BuffLittleLong(dds+16);
2384 dds_height = BuffLittleLong(dds+12);
2385 ddspixels = dds + 128;
2387 if(r_texture_dds_load_alphamode.integer == 0)
2388 if(!(dds_format_flags & 0x1)) // DDPF_ALPHAPIXELS
2389 flags &= ~TEXF_ALPHA;
2391 //flags &= ~TEXF_ALPHA; // disabled, as we DISABLE TEXF_ALPHA in the alpha detection, not enable it!
2392 if ((dds_format_flags & 0x40) && BuffLittleLong(dds+88) == 32)
2394 // very sloppy BGRA 32bit identification
2395 textype = TEXTYPE_BGRA;
2396 flags &= ~TEXF_COMPRESS; // don't let the textype be wrong
2399 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(dds_width, dds_height), bytesperpixel);
2400 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2403 Con_Printf("^1%s: invalid BGRA DDS image\n", filename);
2406 if((r_texture_dds_load_alphamode.integer == 1) && (flags & TEXF_ALPHA))
2409 for (i = 3;i < size;i += 4)
2410 if (ddspixels[i] < 255)
2413 flags &= ~TEXF_ALPHA;
2416 else if (!memcmp(dds+84, "DXT1", 4))
2418 // we need to find out if this is DXT1 (opaque) or DXT1A (transparent)
2419 // LordHavoc: it is my belief that this does not infringe on the
2420 // patent because it is not decoding pixels...
2421 textype = TEXTYPE_DXT1;
2424 //size = ((dds_width+3)/4)*((dds_height+3)/4)*bytesperblock;
2425 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2426 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2429 Con_Printf("^1%s: invalid DXT1 DDS image\n", filename);
2432 if (flags & TEXF_ALPHA)
2434 if (r_texture_dds_load_alphamode.integer == 1)
2437 for (i = 0;i < size;i += bytesperblock)
2438 if (ddspixels[i+0] + ddspixels[i+1] * 256 <= ddspixels[i+2] + ddspixels[i+3] * 256)
2440 // NOTE: this assumes sizeof(unsigned int) == 4
2441 unsigned int data = * (unsigned int *) &(ddspixels[i+4]);
2442 // check if data, in base 4, contains a digit 3 (DXT1: transparent pixel)
2443 if(data & (data<<1) & 0xAAAAAAAA)//rgh
2447 textype = TEXTYPE_DXT1A;
2449 flags &= ~TEXF_ALPHA;
2451 else if (r_texture_dds_load_alphamode.integer == 0)
2452 textype = TEXTYPE_DXT1A;
2455 flags &= ~TEXF_ALPHA;
2459 else if (!memcmp(dds+84, "DXT3", 4) || !memcmp(dds+84, "DXT2", 4))
2461 if(!memcmp(dds+84, "DXT2", 4))
2463 if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
2465 Con_Printf("^1%s: expecting DXT3 image without premultiplied alpha, got DXT2 image with premultiplied alpha\n", filename);
2470 if(flags & TEXF_RGBMULTIPLYBYALPHA)
2472 Con_Printf("^1%s: expecting DXT2 image without premultiplied alpha, got DXT3 image without premultiplied alpha\n", filename);
2475 textype = TEXTYPE_DXT3;
2478 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2479 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2482 Con_Printf("^1%s: invalid DXT3 DDS image\n", filename);
2485 // we currently always assume alpha
2487 else if (!memcmp(dds+84, "DXT5", 4) || !memcmp(dds+84, "DXT4", 4))
2489 if(!memcmp(dds+84, "DXT4", 4))
2491 if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
2493 Con_Printf("^1%s: expecting DXT5 image without premultiplied alpha, got DXT4 image with premultiplied alpha\n", filename);
2498 if(flags & TEXF_RGBMULTIPLYBYALPHA)
2500 Con_Printf("^1%s: expecting DXT4 image without premultiplied alpha, got DXT5 image without premultiplied alpha\n", filename);
2503 textype = TEXTYPE_DXT5;
2506 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2507 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2510 Con_Printf("^1%s: invalid DXT5 DDS image\n", filename);
2513 // we currently always assume alpha
2518 Con_Printf("^1%s: unrecognized/unsupported DDS format\n", filename);
2522 // when requesting a non-alpha texture and we have DXT3/5, convert to DXT1
2523 if(!(flags & TEXF_ALPHA) && (textype == TEXTYPE_DXT3 || textype == TEXTYPE_DXT5))
2525 textype = TEXTYPE_DXT1;
2529 for (i = 0;i < (int)ddssize;i += bytesperblock)
2530 memcpy(&ddspixels[i], &ddspixels[(i<<1)+8], 8);
2534 force_swdecode = false;
2536 (!vid.support.arb_texture_non_power_of_two &&
2538 (dds_width & (dds_width - 1))
2540 (dds_height & (dds_height - 1))
2545 if(vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && !npothack)
2547 if(r_texture_dds_swdecode.integer > 1)
2548 force_swdecode = true;
2552 if(r_texture_dds_swdecode.integer < 1)
2558 force_swdecode = true;
2562 // return whether this texture is transparent
2564 *hasalphaflag = (flags & TEXF_ALPHA) != 0;
2566 // if we SW decode, choose 2 sizes bigger
2569 // this is quarter res, so do not scale down more than we have to
2573 Con_DPrintf("WARNING: fake software decoding of compressed texture %s degraded quality\n", filename);
2576 // this is where we apply gl_picmip
2577 mippixels_start = ddspixels;
2578 mipwidth = dds_width;
2579 mipheight = dds_height;
2580 while(miplevel >= 1 && dds_miplevels >= 1)
2582 if (mipwidth <= 1 && mipheight <= 1)
2584 mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2585 mippixels_start += mipsize; // just skip
2593 mipsize_total = ddssize - 128 - (mippixels_start - ddspixels);
2594 mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2596 // from here on, we do not need the ddspixels and ddssize any more (apart from the statistics entry in glt)
2598 // fake decode S3TC if needed
2601 int mipsize_new = mipsize_total / bytesperblock * 4;
2602 unsigned char *mipnewpixels = (unsigned char *) Mem_Alloc(tempmempool, mipsize_new);
2603 unsigned char *p = mipnewpixels;
2604 for (i = bytesperblock == 16 ? 8 : 0;i < (int)mipsize_total;i += bytesperblock, p += 4)
2606 c = mippixels_start[i] + 256*mippixels_start[i+1] + 65536*mippixels_start[i+2] + 16777216*mippixels_start[i+3];
2607 p[2] = (((c >> 11) & 0x1F) + ((c >> 27) & 0x1F)) * (0.5f / 31.0f * 255.0f);
2608 p[1] = (((c >> 5) & 0x3F) + ((c >> 21) & 0x3F)) * (0.5f / 63.0f * 255.0f);
2609 p[0] = (((c ) & 0x1F) + ((c >> 16) & 0x1F)) * (0.5f / 31.0f * 255.0f);
2610 if(textype == TEXTYPE_DXT5)
2611 p[3] = (0.5 * mippixels_start[i-8] + 0.5 * mippixels_start[i-7]);
2612 else if(textype == TEXTYPE_DXT3)
2614 (mippixels_start[i-8] & 0x0F)
2615 + (mippixels_start[i-8] >> 4)
2616 + (mippixels_start[i-7] & 0x0F)
2617 + (mippixels_start[i-7] >> 4)
2618 + (mippixels_start[i-6] & 0x0F)
2619 + (mippixels_start[i-6] >> 4)
2620 + (mippixels_start[i-5] & 0x0F)
2621 + (mippixels_start[i-5] >> 4)
2622 ) * (0.125f / 15.0f * 255.0f);
2627 textype = TEXTYPE_BGRA;
2631 // as each block becomes a pixel, we must use pixel count for this
2632 mipwidth = (mipwidth + 3) / 4;
2633 mipheight = (mipheight + 3) / 4;
2634 mipsize = bytesperpixel * mipwidth * mipheight;
2635 mippixels_start = mipnewpixels;
2636 mipsize_total = mipsize_new;
2639 // start mip counting
2640 mippixels = mippixels_start;
2642 // calculate average color if requested
2646 Vector4Clear(avgcolor);
2649 for (i = bytesperblock == 16 ? 8 : 0;i < mipsize;i += bytesperblock)
2651 c = mippixels[i] + 256*mippixels[i+1] + 65536*mippixels[i+2] + 16777216*mippixels[i+3];
2652 avgcolor[0] += ((c >> 11) & 0x1F) + ((c >> 27) & 0x1F);
2653 avgcolor[1] += ((c >> 5) & 0x3F) + ((c >> 21) & 0x3F);
2654 avgcolor[2] += ((c ) & 0x1F) + ((c >> 16) & 0x1F);
2655 if(textype == TEXTYPE_DXT5)
2656 avgcolor[3] += (mippixels[i-8] + (int) mippixels[i-7]) * (0.5f / 255.0f);
2657 else if(textype == TEXTYPE_DXT3)
2659 (mippixels_start[i-8] & 0x0F)
2660 + (mippixels_start[i-8] >> 4)
2661 + (mippixels_start[i-7] & 0x0F)
2662 + (mippixels_start[i-7] >> 4)
2663 + (mippixels_start[i-6] & 0x0F)
2664 + (mippixels_start[i-6] >> 4)
2665 + (mippixels_start[i-5] & 0x0F)
2666 + (mippixels_start[i-5] >> 4)
2667 ) * (0.125f / 15.0f);
2669 avgcolor[3] += 1.0f;
2671 f = (float)bytesperblock / mipsize;
2672 avgcolor[0] *= (0.5f / 31.0f) * f;
2673 avgcolor[1] *= (0.5f / 63.0f) * f;
2674 avgcolor[2] *= (0.5f / 31.0f) * f;
2679 for (i = 0;i < mipsize;i += 4)
2681 avgcolor[0] += mippixels[i+2];
2682 avgcolor[1] += mippixels[i+1];
2683 avgcolor[2] += mippixels[i];
2684 avgcolor[3] += mippixels[i+3];
2686 f = (1.0f / 255.0f) * bytesperpixel / mipsize;
2694 // if we want sRGB, convert now
2697 if (vid.support.ext_texture_srgb)
2701 case TEXTYPE_DXT1: textype = TEXTYPE_SRGB_DXT1 ;break;
2702 case TEXTYPE_DXT1A: textype = TEXTYPE_SRGB_DXT1A ;break;
2703 case TEXTYPE_DXT3: textype = TEXTYPE_SRGB_DXT3 ;break;
2704 case TEXTYPE_DXT5: textype = TEXTYPE_SRGB_DXT5 ;break;
2705 case TEXTYPE_RGBA: textype = TEXTYPE_SRGB_RGBA ;break;
2719 for (i = bytesperblock == 16 ? 8 : 0;i < mipsize_total;i += bytesperblock)
2721 int c0, c1, c0new, c1new;
2722 c0 = mippixels_start[i] + 256*mippixels_start[i+1];
2723 r = ((c0 >> 11) & 0x1F);
2724 g = ((c0 >> 5) & 0x3F);
2726 r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2727 g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2728 b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2729 c0new = (r << 11) | (g << 5) | b;
2730 c1 = mippixels_start[i+2] + 256*mippixels_start[i+3];
2731 r = ((c1 >> 11) & 0x1F);
2732 g = ((c1 >> 5) & 0x3F);
2734 r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2735 g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2736 b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2737 c1new = (r << 11) | (g << 5) | b;
2738 // swap the colors if needed to fix order
2739 if(c0 > c1) // thirds
2747 mippixels_start[i+4] ^= 0x55;
2748 mippixels_start[i+5] ^= 0x55;
2749 mippixels_start[i+6] ^= 0x55;
2750 mippixels_start[i+7] ^= 0x55;
2752 else if(c0new == c1new)
2754 mippixels_start[i+4] = 0x00;
2755 mippixels_start[i+5] = 0x00;
2756 mippixels_start[i+6] = 0x00;
2757 mippixels_start[i+7] = 0x00;
2760 else // half + transparent
2767 mippixels_start[i+4] ^= (~mippixels_start[i+4] >> 1) & 0x55;
2768 mippixels_start[i+5] ^= (~mippixels_start[i+5] >> 1) & 0x55;
2769 mippixels_start[i+6] ^= (~mippixels_start[i+6] >> 1) & 0x55;
2770 mippixels_start[i+7] ^= (~mippixels_start[i+7] >> 1) & 0x55;
2773 mippixels_start[i] = c0new & 255;
2774 mippixels_start[i+1] = c0new >> 8;
2775 mippixels_start[i+2] = c1new & 255;
2776 mippixels_start[i+3] = c1new >> 8;
2781 Image_MakeLinearColorsFromsRGB(mippixels, mippixels, mipsize_total / bytesperblock);
2789 // when not requesting mipmaps, do not load them
2790 if(!(flags & TEXF_MIPMAP))
2793 if (dds_miplevels >= 1)
2794 flags |= TEXF_MIPMAP;
2796 flags &= ~TEXF_MIPMAP;
2798 texinfo = R_GetTexTypeInfo(textype, flags);
2800 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
2801 strlcpy (glt->identifier, filename, sizeof(glt->identifier));
2803 glt->chain = pool->gltchain;
2804 pool->gltchain = glt;
2805 glt->inputwidth = mipwidth;
2806 glt->inputheight = mipheight;
2807 glt->inputdepth = 1;
2809 glt->textype = texinfo;
2810 glt->texturetype = GLTEXTURETYPE_2D;
2811 glt->inputdatasize = ddssize;
2812 glt->glinternalformat = texinfo->glinternalformat;
2813 glt->glformat = texinfo->glformat;
2814 glt->gltype = texinfo->gltype;
2815 glt->bytesperpixel = texinfo->internalbytesperpixel;
2817 glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
2818 glt->tilewidth = mipwidth;
2819 glt->tileheight = mipheight;
2821 glt->miplevels = dds_miplevels;
2825 for (glt->tilewidth = 1;glt->tilewidth < mipwidth;glt->tilewidth <<= 1);
2826 for (glt->tileheight = 1;glt->tileheight < mipheight;glt->tileheight <<= 1);
2829 // texture uploading can take a while, so make sure we're sending keepalives
2830 CL_KeepaliveMessage(false);
2832 // create the texture object
2833 switch(vid.renderpath)
2835 case RENDERPATH_GL11:
2836 case RENDERPATH_GL13:
2837 case RENDERPATH_GL20:
2838 case RENDERPATH_GLES1:
2839 case RENDERPATH_GLES2:
2841 GL_ActiveTexture(0);
2842 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
2843 qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
2844 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
2846 case RENDERPATH_D3D9:
2849 D3DFORMAT d3dformat;
2854 case TEXTYPE_BGRA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
2855 case TEXTYPE_DXT1: case TEXTYPE_DXT1A: d3dformat = D3DFMT_DXT1;break;
2856 case TEXTYPE_DXT3: d3dformat = D3DFMT_DXT3;break;
2857 case TEXTYPE_DXT5: d3dformat = D3DFMT_DXT5;break;
2858 default: d3dformat = D3DFMT_A8R8G8B8;Host_Error("R_LoadTextureDDSFile: unsupported texture type %i when picking D3DFMT", (int)textype);break;
2861 d3dpool = D3DPOOL_MANAGED;
2862 IDirect3DDevice9_CreateTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->miplevels, d3dusage, d3dformat, d3dpool, (IDirect3DTexture9 **)&glt->d3dtexture, NULL);
2866 case RENDERPATH_D3D10:
2867 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2869 case RENDERPATH_D3D11:
2870 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2872 case RENDERPATH_SOFT:
2873 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);
2877 // upload the texture
2878 // we need to restore the texture binding after finishing the upload
2879 mipcomplete = false;
2881 for (mip = 0;mip <= dds_miplevels;mip++) // <= to include the not-counted "largest" miplevel
2883 unsigned char *upload_mippixels = mippixels;
2884 int upload_mipwidth = mipwidth;
2885 int upload_mipheight = mipheight;
2886 mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2887 if (mippixels + mipsize > mippixels_start + mipsize_total)
2891 upload_mipwidth = (glt->tilewidth >> mip);
2892 upload_mipheight = (glt->tileheight >> mip);
2893 if(upload_mipwidth != mipwidth || upload_mipheight != mipheight)
2894 // I _think_ they always mismatch, but I was too lazy
2895 // to properly check, and this test here is really
2898 upload_mippixels = (unsigned char *) Mem_Alloc(tempmempool, 4 * upload_mipwidth * upload_mipheight);
2899 Image_Resample32(mippixels, mipwidth, mipheight, 1, upload_mippixels, upload_mipwidth, upload_mipheight, 1, r_lerpimages.integer);
2902 switch(vid.renderpath)
2904 case RENDERPATH_GL11:
2905 case RENDERPATH_GL13:
2906 case RENDERPATH_GL20:
2907 case RENDERPATH_GLES1:
2908 case RENDERPATH_GLES2:
2911 qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, mipsize, upload_mippixels);CHECKGLERROR
2915 qglTexImage2D(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, glt->glformat, glt->gltype, upload_mippixels);CHECKGLERROR
2918 case RENDERPATH_D3D9:
2921 D3DLOCKED_RECT d3dlockedrect;
2922 if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
2924 memcpy(d3dlockedrect.pBits, upload_mippixels, mipsize);
2925 IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
2931 case RENDERPATH_D3D10:
2932 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2934 case RENDERPATH_D3D11:
2935 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2937 case RENDERPATH_SOFT:
2939 Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2941 DPSOFTRAST_Texture_UpdateFull(glt->texnum, upload_mippixels);
2942 // DPSOFTRAST calculates its own mipmaps
2943 mip = dds_miplevels;
2946 if(upload_mippixels != mippixels)
2947 Mem_Free(upload_mippixels);
2948 mippixels += mipsize;
2949 if (mipwidth <= 1 && mipheight <= 1)
2960 // after upload we have to set some parameters...
2961 switch(vid.renderpath)
2963 case RENDERPATH_GL11:
2964 case RENDERPATH_GL13:
2965 case RENDERPATH_GL20:
2966 case RENDERPATH_GLES1:
2967 case RENDERPATH_GLES2:
2968 #ifdef GL_TEXTURE_MAX_LEVEL
2969 if (dds_miplevels >= 1 && !mipcomplete)
2971 // need to set GL_TEXTURE_MAX_LEVEL
2972 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR
2975 GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
2976 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2978 case RENDERPATH_D3D9:
2980 glt->d3daddressw = 0;
2981 if (glt->flags & TEXF_CLAMP)
2983 glt->d3daddressu = D3DTADDRESS_CLAMP;
2984 glt->d3daddressv = D3DTADDRESS_CLAMP;
2985 if (glt->tiledepth > 1)
2986 glt->d3daddressw = D3DTADDRESS_CLAMP;
2990 glt->d3daddressu = D3DTADDRESS_WRAP;
2991 glt->d3daddressv = D3DTADDRESS_WRAP;
2992 if (glt->tiledepth > 1)
2993 glt->d3daddressw = D3DTADDRESS_WRAP;
2995 glt->d3dmipmaplodbias = 0;
2996 glt->d3dmaxmiplevel = 0;
2997 glt->d3dmaxmiplevelfilter = 0;
2998 if (glt->flags & TEXF_MIPMAP)
3000 glt->d3dminfilter = d3d_filter_mipmin;
3001 glt->d3dmagfilter = d3d_filter_mipmag;
3002 glt->d3dmipfilter = d3d_filter_mipmix;
3006 glt->d3dminfilter = d3d_filter_flatmin;
3007 glt->d3dmagfilter = d3d_filter_flatmag;
3008 glt->d3dmipfilter = d3d_filter_flatmix;
3012 case RENDERPATH_D3D10:
3013 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3015 case RENDERPATH_D3D11:
3016 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3018 case RENDERPATH_SOFT:
3019 if (glt->flags & TEXF_FORCELINEAR)
3020 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
3021 else if (glt->flags & TEXF_FORCENEAREST)
3022 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
3023 else if (glt->flags & TEXF_MIPMAP)
3024 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
3026 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
3032 Mem_Free((unsigned char *) mippixels_start);
3033 return (rtexture_t *)glt;
3036 int R_TextureWidth(rtexture_t *rt)
3038 return rt ? ((gltexture_t *)rt)->inputwidth : 0;
3041 int R_TextureHeight(rtexture_t *rt)
3043 return rt ? ((gltexture_t *)rt)->inputheight : 0;
3046 int R_TextureFlags(rtexture_t *rt)
3048 return rt ? ((gltexture_t *)rt)->flags : 0;
3051 void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int z, int width, int height, int depth)
3053 gltexture_t *glt = (gltexture_t *)rt;
3055 Host_Error("R_UpdateTexture: no data supplied");
3057 Host_Error("R_UpdateTexture: no texture supplied");
3058 if (!glt->texnum && !glt->d3dtexture)
3060 Con_DPrintf("R_UpdateTexture: texture %p \"%s\" in pool %p has not been uploaded yet\n", (void *)glt, glt->identifier, (void *)glt->pool);
3063 // update part of the texture
3064 if (glt->bufferpixels)
3067 int bpp = glt->bytesperpixel;
3068 int inputskip = width*bpp;
3069 int outputskip = glt->tilewidth*bpp;
3070 const unsigned char *input = data;
3071 unsigned char *output = glt->bufferpixels;
3072 if (glt->inputdepth != 1 || glt->sides != 1)
3073 Sys_Error("R_UpdateTexture on buffered texture that is not 2D\n");
3083 input -= y*inputskip;
3086 if (width > glt->tilewidth - x)
3087 width = glt->tilewidth - x;
3088 if (height > glt->tileheight - y)
3089 height = glt->tileheight - y;
3090 if (width < 1 || height < 1)
3093 glt->buffermodified = true;
3094 output += y*outputskip + x*bpp;
3095 for (j = 0;j < height;j++, output += outputskip, input += inputskip)
3096 memcpy(output, input, width*bpp);
3098 else if (x || y || z || width != glt->inputwidth || height != glt->inputheight || depth != glt->inputdepth)
3099 R_UploadPartialTexture(glt, data, x, y, z, width, height, depth);
3101 R_UploadFullTexture(glt, data);
3104 int R_RealGetTexture(rtexture_t *rt)
3109 glt = (gltexture_t *)rt;
3110 if (glt->flags & GLTEXF_DYNAMIC)
3111 R_UpdateDynamicTexture(glt);
3112 if (glt->buffermodified && glt->bufferpixels)
3114 glt->buffermodified = false;
3115 R_UploadFullTexture(glt, glt->bufferpixels);
3124 void R_ClearTexture (rtexture_t *rt)
3126 gltexture_t *glt = (gltexture_t *)rt;
3128 R_UploadFullTexture(glt, NULL);
3131 int R_PicmipForFlags(int flags)
3134 if(flags & TEXF_PICMIP)
3136 miplevel += gl_picmip.integer;
3137 if (flags & TEXF_ISWORLD)
3139 if (r_picmipworld.integer)
3140 miplevel += gl_picmip_world.integer;
3144 else if (flags & TEXF_ISSPRITE)
3146 if (r_picmipsprites.integer)
3147 miplevel += gl_picmip_sprites.integer;
3152 miplevel += gl_picmip_other.integer;
3154 return max(0, miplevel);