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 = 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 = 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 = glt->texturetype == TEXTYPE_DEPTHBUFFER24STENCIL8;
1975 glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
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 // ELUAN: FIXME: separate this code
2193 #include "ktx10/include/ktx.h"
2196 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
2198 int i, size, dds_format_flags, dds_miplevels, dds_width, dds_height;
2201 int bytesperblock, bytesperpixel;
2204 gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
2205 textypeinfo_t *texinfo;
2206 int mip, mipwidth, mipheight, mipsize, mipsize_total;
2207 unsigned int c, r, g, b;
2208 GLint oldbindtexnum = 0;
2209 unsigned char *mippixels;
2210 unsigned char *mippixels_start;
2211 unsigned char *ddspixels;
2213 fs_offset_t ddsfilesize;
2214 unsigned int ddssize;
2215 qboolean force_swdecode, npothack;
2217 // ELUAN: FIXME: separate this code
2221 KTX_dimensions sizes;
2224 if (cls.state == ca_dedicated)
2228 // ELUAN: FIXME: separate this code
2229 if (vid.renderpath != RENDERPATH_GLES2)
2231 Con_DPrintf("KTX texture format is only supported on the GLES2 renderpath\n");
2235 // some textures are specified with extensions, so it becomes .tga.dds
2236 FS_StripExtension (filename, vabuf2, sizeof(vabuf2));
2237 FS_StripExtension (vabuf2, vabuf, sizeof(vabuf));
2238 FS_DefaultExtension (vabuf, ".ktx", sizeof(vabuf));
2239 strsize = strlen(vabuf);
2241 for (i = 0; i <= strsize - 4; i++) // copy null termination
2242 vabuf[i] = vabuf[i + 4];
2244 Con_DPrintf("Loading %s...\n", vabuf);
2245 dds = FS_LoadFile(vabuf, tempmempool, true, &ddsfilesize);
2246 ddssize = ddsfilesize;
2250 Con_DPrintf("Not found!\n");
2251 return NULL; // not found
2253 Con_DPrintf("Found!\n");
2255 if (flags & TEXF_ALPHA)
2257 Con_DPrintf("KTX texture with alpha not supported yet, disabling\n");
2258 flags &= ~TEXF_ALPHA;
2264 GLboolean isMipmapped;
2265 KTX_error_code ktxerror;
2267 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
2269 // texture uploading can take a while, so make sure we're sending keepalives
2270 CL_KeepaliveMessage(false);
2272 // create the texture object
2274 GL_ActiveTexture(0);
2275 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[GLTEXTURETYPE_2D]);
2276 qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
2277 qglBindTexture(gltexturetypeenums[GLTEXTURETYPE_2D], glt->texnum);CHECKGLERROR
2279 // upload the texture
2280 // we need to restore the texture binding after finishing the upload
2282 // NOTE: some drivers fail with ETC1 NPOT (only PowerVR?). This may make the driver crash later.
2283 ktxerror = ktxLoadTextureM(dds, ddssize, &glt->texnum, &target, &sizes, &isMipmapped, &glerror,
2284 0, NULL);// can't CHECKGLERROR, the lib catches it
2286 // FIXME: delete texture if we fail here
2287 if (target != GL_TEXTURE_2D)
2289 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2291 Con_DPrintf("%s target != GL_TEXTURE_2D, target == %x\n", vabuf, target);
2292 return NULL; // FIXME: delete the texture from memory
2295 if (KTX_SUCCESS == ktxerror)
2297 textype = TEXTYPE_ETC1;
2298 flags &= ~TEXF_COMPRESS; // don't let the textype be wrong
2300 // return whether this texture is transparent
2302 *hasalphaflag = (flags & TEXF_ALPHA) != 0;
2304 // TODO: apply gl_picmip
2307 // TODO: only load mipmaps if requested
2310 flags |= TEXF_MIPMAP;
2312 flags &= ~TEXF_MIPMAP;
2314 texinfo = R_GetTexTypeInfo(textype, flags);
2316 strlcpy (glt->identifier, vabuf, sizeof(glt->identifier));
2318 glt->chain = pool->gltchain;
2319 pool->gltchain = glt;
2320 glt->inputwidth = sizes.width;
2321 glt->inputheight = sizes.height;
2322 glt->inputdepth = 1;
2324 glt->textype = texinfo;
2325 glt->texturetype = GLTEXTURETYPE_2D;
2326 glt->inputdatasize = ddssize;
2327 glt->glinternalformat = texinfo->glinternalformat;
2328 glt->glformat = texinfo->glformat;
2329 glt->gltype = texinfo->gltype;
2330 glt->bytesperpixel = texinfo->internalbytesperpixel;
2332 glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
2333 glt->tilewidth = sizes.width;
2334 glt->tileheight = sizes.height;
2336 glt->miplevels = isMipmapped ? 1 : 0; // FIXME
2338 // after upload we have to set some parameters...
2339 #ifdef GL_TEXTURE_MAX_LEVEL
2341 if (dds_miplevels >= 1 && !mipcomplete)
2343 // need to set GL_TEXTURE_MAX_LEVEL
2344 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR
2348 GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
2350 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2352 return (rtexture_t *)glt;
2356 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2358 Con_DPrintf("KTX texture %s failed to load: %x\n", vabuf, ktxerror);
2362 #endif // __ANDROID__
2364 dds = FS_LoadFile(filename, tempmempool, true, &ddsfilesize);
2365 ddssize = ddsfilesize;
2369 if (r_texture_dds_load_logfailure.integer && (r_texture_dds_load_logfailure.integer >= 2 || !optionaltexture))
2370 Log_Printf("ddstexturefailures.log", "%s\n", filename);
2371 return NULL; // not found
2374 if (ddsfilesize <= 128 || memcmp(dds, "DDS ", 4) || ddssize < (unsigned int)BuffLittleLong(dds+4) || BuffLittleLong(dds+76) != 32)
2377 Con_Printf("^1%s: not a DDS image\n", filename);
2381 //dds_flags = BuffLittleLong(dds+8);
2382 dds_format_flags = BuffLittleLong(dds+80);
2383 dds_miplevels = (BuffLittleLong(dds+108) & 0x400000) ? BuffLittleLong(dds+28) : 1;
2384 dds_width = BuffLittleLong(dds+16);
2385 dds_height = BuffLittleLong(dds+12);
2386 ddspixels = dds + 128;
2388 if(r_texture_dds_load_alphamode.integer == 0)
2389 if(!(dds_format_flags & 0x1)) // DDPF_ALPHAPIXELS
2390 flags &= ~TEXF_ALPHA;
2392 //flags &= ~TEXF_ALPHA; // disabled, as we DISABLE TEXF_ALPHA in the alpha detection, not enable it!
2393 if ((dds_format_flags & 0x40) && BuffLittleLong(dds+88) == 32)
2395 // very sloppy BGRA 32bit identification
2396 textype = TEXTYPE_BGRA;
2397 flags &= ~TEXF_COMPRESS; // don't let the textype be wrong
2400 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(dds_width, dds_height), bytesperpixel);
2401 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2404 Con_Printf("^1%s: invalid BGRA DDS image\n", filename);
2407 if((r_texture_dds_load_alphamode.integer == 1) && (flags & TEXF_ALPHA))
2410 for (i = 3;i < size;i += 4)
2411 if (ddspixels[i] < 255)
2414 flags &= ~TEXF_ALPHA;
2417 else if (!memcmp(dds+84, "DXT1", 4))
2419 // we need to find out if this is DXT1 (opaque) or DXT1A (transparent)
2420 // LordHavoc: it is my belief that this does not infringe on the
2421 // patent because it is not decoding pixels...
2422 textype = TEXTYPE_DXT1;
2425 //size = ((dds_width+3)/4)*((dds_height+3)/4)*bytesperblock;
2426 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2427 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2430 Con_Printf("^1%s: invalid DXT1 DDS image\n", filename);
2433 if (flags & TEXF_ALPHA)
2435 if (r_texture_dds_load_alphamode.integer == 1)
2438 for (i = 0;i < size;i += bytesperblock)
2439 if (ddspixels[i+0] + ddspixels[i+1] * 256 <= ddspixels[i+2] + ddspixels[i+3] * 256)
2441 // NOTE: this assumes sizeof(unsigned int) == 4
2442 unsigned int data = * (unsigned int *) &(ddspixels[i+4]);
2443 // check if data, in base 4, contains a digit 3 (DXT1: transparent pixel)
2444 if(data & (data<<1) & 0xAAAAAAAA)//rgh
2448 textype = TEXTYPE_DXT1A;
2450 flags &= ~TEXF_ALPHA;
2452 else if (r_texture_dds_load_alphamode.integer == 0)
2453 textype = TEXTYPE_DXT1A;
2456 flags &= ~TEXF_ALPHA;
2460 else if (!memcmp(dds+84, "DXT3", 4) || !memcmp(dds+84, "DXT2", 4))
2462 if(!memcmp(dds+84, "DXT2", 4))
2464 if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
2466 Con_Printf("^1%s: expecting DXT3 image without premultiplied alpha, got DXT2 image with premultiplied alpha\n", filename);
2471 if(flags & TEXF_RGBMULTIPLYBYALPHA)
2473 Con_Printf("^1%s: expecting DXT2 image without premultiplied alpha, got DXT3 image without premultiplied alpha\n", filename);
2476 textype = TEXTYPE_DXT3;
2479 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2480 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2483 Con_Printf("^1%s: invalid DXT3 DDS image\n", filename);
2486 // we currently always assume alpha
2488 else if (!memcmp(dds+84, "DXT5", 4) || !memcmp(dds+84, "DXT4", 4))
2490 if(!memcmp(dds+84, "DXT4", 4))
2492 if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
2494 Con_Printf("^1%s: expecting DXT5 image without premultiplied alpha, got DXT4 image with premultiplied alpha\n", filename);
2499 if(flags & TEXF_RGBMULTIPLYBYALPHA)
2501 Con_Printf("^1%s: expecting DXT4 image without premultiplied alpha, got DXT5 image without premultiplied alpha\n", filename);
2504 textype = TEXTYPE_DXT5;
2507 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2508 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2511 Con_Printf("^1%s: invalid DXT5 DDS image\n", filename);
2514 // we currently always assume alpha
2519 Con_Printf("^1%s: unrecognized/unsupported DDS format\n", filename);
2523 // when requesting a non-alpha texture and we have DXT3/5, convert to DXT1
2524 if(!(flags & TEXF_ALPHA) && (textype == TEXTYPE_DXT3 || textype == TEXTYPE_DXT5))
2526 textype = TEXTYPE_DXT1;
2530 for (i = 0;i < (int)ddssize;i += bytesperblock)
2531 memcpy(&ddspixels[i], &ddspixels[(i<<1)+8], 8);
2535 force_swdecode = false;
2537 (!vid.support.arb_texture_non_power_of_two &&
2539 (dds_width & (dds_width - 1))
2541 (dds_height & (dds_height - 1))
2546 if(vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && !npothack)
2548 if(r_texture_dds_swdecode.integer > 1)
2549 force_swdecode = true;
2553 if(r_texture_dds_swdecode.integer < 1)
2559 force_swdecode = true;
2563 // return whether this texture is transparent
2565 *hasalphaflag = (flags & TEXF_ALPHA) != 0;
2567 // if we SW decode, choose 2 sizes bigger
2570 // this is quarter res, so do not scale down more than we have to
2574 Con_DPrintf("WARNING: fake software decoding of compressed texture %s degraded quality\n", filename);
2577 // this is where we apply gl_picmip
2578 mippixels_start = ddspixels;
2579 mipwidth = dds_width;
2580 mipheight = dds_height;
2581 while(miplevel >= 1 && dds_miplevels >= 1)
2583 if (mipwidth <= 1 && mipheight <= 1)
2585 mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2586 mippixels_start += mipsize; // just skip
2594 mipsize_total = ddssize - 128 - (mippixels_start - ddspixels);
2595 mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2597 // from here on, we do not need the ddspixels and ddssize any more (apart from the statistics entry in glt)
2599 // fake decode S3TC if needed
2602 int mipsize_new = mipsize_total / bytesperblock * 4;
2603 unsigned char *mipnewpixels = (unsigned char *) Mem_Alloc(tempmempool, mipsize_new);
2604 unsigned char *p = mipnewpixels;
2605 for (i = bytesperblock == 16 ? 8 : 0;i < (int)mipsize_total;i += bytesperblock, p += 4)
2607 c = mippixels_start[i] + 256*mippixels_start[i+1] + 65536*mippixels_start[i+2] + 16777216*mippixels_start[i+3];
2608 p[2] = (((c >> 11) & 0x1F) + ((c >> 27) & 0x1F)) * (0.5f / 31.0f * 255.0f);
2609 p[1] = (((c >> 5) & 0x3F) + ((c >> 21) & 0x3F)) * (0.5f / 63.0f * 255.0f);
2610 p[0] = (((c ) & 0x1F) + ((c >> 16) & 0x1F)) * (0.5f / 31.0f * 255.0f);
2611 if(textype == TEXTYPE_DXT5)
2612 p[3] = (0.5 * mippixels_start[i-8] + 0.5 * mippixels_start[i-7]);
2613 else if(textype == TEXTYPE_DXT3)
2615 (mippixels_start[i-8] & 0x0F)
2616 + (mippixels_start[i-8] >> 4)
2617 + (mippixels_start[i-7] & 0x0F)
2618 + (mippixels_start[i-7] >> 4)
2619 + (mippixels_start[i-6] & 0x0F)
2620 + (mippixels_start[i-6] >> 4)
2621 + (mippixels_start[i-5] & 0x0F)
2622 + (mippixels_start[i-5] >> 4)
2623 ) * (0.125f / 15.0f * 255.0f);
2628 textype = TEXTYPE_BGRA;
2632 // as each block becomes a pixel, we must use pixel count for this
2633 mipwidth = (mipwidth + 3) / 4;
2634 mipheight = (mipheight + 3) / 4;
2635 mipsize = bytesperpixel * mipwidth * mipheight;
2636 mippixels_start = mipnewpixels;
2637 mipsize_total = mipsize_new;
2640 // start mip counting
2641 mippixels = mippixels_start;
2643 // calculate average color if requested
2647 Vector4Clear(avgcolor);
2650 for (i = bytesperblock == 16 ? 8 : 0;i < mipsize;i += bytesperblock)
2652 c = mippixels[i] + 256*mippixels[i+1] + 65536*mippixels[i+2] + 16777216*mippixels[i+3];
2653 avgcolor[0] += ((c >> 11) & 0x1F) + ((c >> 27) & 0x1F);
2654 avgcolor[1] += ((c >> 5) & 0x3F) + ((c >> 21) & 0x3F);
2655 avgcolor[2] += ((c ) & 0x1F) + ((c >> 16) & 0x1F);
2656 if(textype == TEXTYPE_DXT5)
2657 avgcolor[3] += (mippixels[i-8] + (int) mippixels[i-7]) * (0.5f / 255.0f);
2658 else if(textype == TEXTYPE_DXT3)
2660 (mippixels_start[i-8] & 0x0F)
2661 + (mippixels_start[i-8] >> 4)
2662 + (mippixels_start[i-7] & 0x0F)
2663 + (mippixels_start[i-7] >> 4)
2664 + (mippixels_start[i-6] & 0x0F)
2665 + (mippixels_start[i-6] >> 4)
2666 + (mippixels_start[i-5] & 0x0F)
2667 + (mippixels_start[i-5] >> 4)
2668 ) * (0.125f / 15.0f);
2670 avgcolor[3] += 1.0f;
2672 f = (float)bytesperblock / mipsize;
2673 avgcolor[0] *= (0.5f / 31.0f) * f;
2674 avgcolor[1] *= (0.5f / 63.0f) * f;
2675 avgcolor[2] *= (0.5f / 31.0f) * f;
2680 for (i = 0;i < mipsize;i += 4)
2682 avgcolor[0] += mippixels[i+2];
2683 avgcolor[1] += mippixels[i+1];
2684 avgcolor[2] += mippixels[i];
2685 avgcolor[3] += mippixels[i+3];
2687 f = (1.0f / 255.0f) * bytesperpixel / mipsize;
2695 // if we want sRGB, convert now
2698 if (vid.support.ext_texture_srgb)
2702 case TEXTYPE_DXT1: textype = TEXTYPE_SRGB_DXT1 ;break;
2703 case TEXTYPE_DXT1A: textype = TEXTYPE_SRGB_DXT1A ;break;
2704 case TEXTYPE_DXT3: textype = TEXTYPE_SRGB_DXT3 ;break;
2705 case TEXTYPE_DXT5: textype = TEXTYPE_SRGB_DXT5 ;break;
2706 case TEXTYPE_RGBA: textype = TEXTYPE_SRGB_RGBA ;break;
2720 for (i = bytesperblock == 16 ? 8 : 0;i < mipsize_total;i += bytesperblock)
2722 int c0, c1, c0new, c1new;
2723 c0 = mippixels_start[i] + 256*mippixels_start[i+1];
2724 r = ((c0 >> 11) & 0x1F);
2725 g = ((c0 >> 5) & 0x3F);
2727 r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2728 g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2729 b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2730 c0new = (r << 11) | (g << 5) | b;
2731 c1 = mippixels_start[i+2] + 256*mippixels_start[i+3];
2732 r = ((c1 >> 11) & 0x1F);
2733 g = ((c1 >> 5) & 0x3F);
2735 r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2736 g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2737 b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2738 c1new = (r << 11) | (g << 5) | b;
2739 // swap the colors if needed to fix order
2740 if(c0 > c1) // thirds
2748 mippixels_start[i+4] ^= 0x55;
2749 mippixels_start[i+5] ^= 0x55;
2750 mippixels_start[i+6] ^= 0x55;
2751 mippixels_start[i+7] ^= 0x55;
2753 else if(c0new == c1new)
2755 mippixels_start[i+4] = 0x00;
2756 mippixels_start[i+5] = 0x00;
2757 mippixels_start[i+6] = 0x00;
2758 mippixels_start[i+7] = 0x00;
2761 else // half + transparent
2768 mippixels_start[i+4] ^= (~mippixels_start[i+4] >> 1) & 0x55;
2769 mippixels_start[i+5] ^= (~mippixels_start[i+5] >> 1) & 0x55;
2770 mippixels_start[i+6] ^= (~mippixels_start[i+6] >> 1) & 0x55;
2771 mippixels_start[i+7] ^= (~mippixels_start[i+7] >> 1) & 0x55;
2774 mippixels_start[i] = c0new & 255;
2775 mippixels_start[i+1] = c0new >> 8;
2776 mippixels_start[i+2] = c1new & 255;
2777 mippixels_start[i+3] = c1new >> 8;
2782 Image_MakeLinearColorsFromsRGB(mippixels, mippixels, mipsize_total / bytesperblock);
2790 // when not requesting mipmaps, do not load them
2791 if(!(flags & TEXF_MIPMAP))
2794 if (dds_miplevels >= 1)
2795 flags |= TEXF_MIPMAP;
2797 flags &= ~TEXF_MIPMAP;
2799 texinfo = R_GetTexTypeInfo(textype, flags);
2801 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
2802 strlcpy (glt->identifier, filename, sizeof(glt->identifier));
2804 glt->chain = pool->gltchain;
2805 pool->gltchain = glt;
2806 glt->inputwidth = mipwidth;
2807 glt->inputheight = mipheight;
2808 glt->inputdepth = 1;
2810 glt->textype = texinfo;
2811 glt->texturetype = GLTEXTURETYPE_2D;
2812 glt->inputdatasize = ddssize;
2813 glt->glinternalformat = texinfo->glinternalformat;
2814 glt->glformat = texinfo->glformat;
2815 glt->gltype = texinfo->gltype;
2816 glt->bytesperpixel = texinfo->internalbytesperpixel;
2818 glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
2819 glt->tilewidth = mipwidth;
2820 glt->tileheight = mipheight;
2822 glt->miplevels = dds_miplevels;
2826 for (glt->tilewidth = 1;glt->tilewidth < mipwidth;glt->tilewidth <<= 1);
2827 for (glt->tileheight = 1;glt->tileheight < mipheight;glt->tileheight <<= 1);
2830 // texture uploading can take a while, so make sure we're sending keepalives
2831 CL_KeepaliveMessage(false);
2833 // create the texture object
2834 switch(vid.renderpath)
2836 case RENDERPATH_GL11:
2837 case RENDERPATH_GL13:
2838 case RENDERPATH_GL20:
2839 case RENDERPATH_GLES1:
2840 case RENDERPATH_GLES2:
2842 GL_ActiveTexture(0);
2843 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
2844 qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
2845 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
2847 case RENDERPATH_D3D9:
2850 D3DFORMAT d3dformat;
2855 case TEXTYPE_BGRA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
2856 case TEXTYPE_DXT1: case TEXTYPE_DXT1A: d3dformat = D3DFMT_DXT1;break;
2857 case TEXTYPE_DXT3: d3dformat = D3DFMT_DXT3;break;
2858 case TEXTYPE_DXT5: d3dformat = D3DFMT_DXT5;break;
2859 default: d3dformat = D3DFMT_A8R8G8B8;Host_Error("R_LoadTextureDDSFile: unsupported texture type %i when picking D3DFMT", (int)textype);break;
2862 d3dpool = D3DPOOL_MANAGED;
2863 IDirect3DDevice9_CreateTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->miplevels, d3dusage, d3dformat, d3dpool, (IDirect3DTexture9 **)&glt->d3dtexture, NULL);
2867 case RENDERPATH_D3D10:
2868 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2870 case RENDERPATH_D3D11:
2871 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2873 case RENDERPATH_SOFT:
2874 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);
2878 // upload the texture
2879 // we need to restore the texture binding after finishing the upload
2880 mipcomplete = false;
2882 for (mip = 0;mip <= dds_miplevels;mip++) // <= to include the not-counted "largest" miplevel
2884 unsigned char *upload_mippixels = mippixels;
2885 int upload_mipwidth = mipwidth;
2886 int upload_mipheight = mipheight;
2887 mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2888 if (mippixels + mipsize > mippixels_start + mipsize_total)
2892 upload_mipwidth = (glt->tilewidth >> mip);
2893 upload_mipheight = (glt->tileheight >> mip);
2894 if(upload_mipwidth != mipwidth || upload_mipheight != mipheight)
2895 // I _think_ they always mismatch, but I was too lazy
2896 // to properly check, and this test here is really
2899 upload_mippixels = (unsigned char *) Mem_Alloc(tempmempool, 4 * upload_mipwidth * upload_mipheight);
2900 Image_Resample32(mippixels, mipwidth, mipheight, 1, upload_mippixels, upload_mipwidth, upload_mipheight, 1, r_lerpimages.integer);
2903 switch(vid.renderpath)
2905 case RENDERPATH_GL11:
2906 case RENDERPATH_GL13:
2907 case RENDERPATH_GL20:
2908 case RENDERPATH_GLES1:
2909 case RENDERPATH_GLES2:
2912 qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, mipsize, upload_mippixels);CHECKGLERROR
2916 qglTexImage2D(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, glt->glformat, glt->gltype, upload_mippixels);CHECKGLERROR
2919 case RENDERPATH_D3D9:
2922 D3DLOCKED_RECT d3dlockedrect;
2923 if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
2925 memcpy(d3dlockedrect.pBits, upload_mippixels, mipsize);
2926 IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
2932 case RENDERPATH_D3D10:
2933 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2935 case RENDERPATH_D3D11:
2936 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2938 case RENDERPATH_SOFT:
2940 Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2942 DPSOFTRAST_Texture_UpdateFull(glt->texnum, upload_mippixels);
2943 // DPSOFTRAST calculates its own mipmaps
2944 mip = dds_miplevels;
2947 if(upload_mippixels != mippixels)
2948 Mem_Free(upload_mippixels);
2949 mippixels += mipsize;
2950 if (mipwidth <= 1 && mipheight <= 1)
2961 // after upload we have to set some parameters...
2962 switch(vid.renderpath)
2964 case RENDERPATH_GL11:
2965 case RENDERPATH_GL13:
2966 case RENDERPATH_GL20:
2967 case RENDERPATH_GLES1:
2968 case RENDERPATH_GLES2:
2969 #ifdef GL_TEXTURE_MAX_LEVEL
2970 if (dds_miplevels >= 1 && !mipcomplete)
2972 // need to set GL_TEXTURE_MAX_LEVEL
2973 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR
2976 GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
2977 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2979 case RENDERPATH_D3D9:
2981 glt->d3daddressw = 0;
2982 if (glt->flags & TEXF_CLAMP)
2984 glt->d3daddressu = D3DTADDRESS_CLAMP;
2985 glt->d3daddressv = D3DTADDRESS_CLAMP;
2986 if (glt->tiledepth > 1)
2987 glt->d3daddressw = D3DTADDRESS_CLAMP;
2991 glt->d3daddressu = D3DTADDRESS_WRAP;
2992 glt->d3daddressv = D3DTADDRESS_WRAP;
2993 if (glt->tiledepth > 1)
2994 glt->d3daddressw = D3DTADDRESS_WRAP;
2996 glt->d3dmipmaplodbias = 0;
2997 glt->d3dmaxmiplevel = 0;
2998 glt->d3dmaxmiplevelfilter = 0;
2999 if (glt->flags & TEXF_MIPMAP)
3001 glt->d3dminfilter = d3d_filter_mipmin;
3002 glt->d3dmagfilter = d3d_filter_mipmag;
3003 glt->d3dmipfilter = d3d_filter_mipmix;
3007 glt->d3dminfilter = d3d_filter_flatmin;
3008 glt->d3dmagfilter = d3d_filter_flatmag;
3009 glt->d3dmipfilter = d3d_filter_flatmix;
3013 case RENDERPATH_D3D10:
3014 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3016 case RENDERPATH_D3D11:
3017 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3019 case RENDERPATH_SOFT:
3020 if (glt->flags & TEXF_FORCELINEAR)
3021 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
3022 else if (glt->flags & TEXF_FORCENEAREST)
3023 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
3024 else if (glt->flags & TEXF_MIPMAP)
3025 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
3027 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
3033 Mem_Free((unsigned char *) mippixels_start);
3034 return (rtexture_t *)glt;
3037 int R_TextureWidth(rtexture_t *rt)
3039 return rt ? ((gltexture_t *)rt)->inputwidth : 0;
3042 int R_TextureHeight(rtexture_t *rt)
3044 return rt ? ((gltexture_t *)rt)->inputheight : 0;
3047 int R_TextureFlags(rtexture_t *rt)
3049 return rt ? ((gltexture_t *)rt)->flags : 0;
3052 void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int z, int width, int height, int depth)
3054 gltexture_t *glt = (gltexture_t *)rt;
3056 Host_Error("R_UpdateTexture: no data supplied");
3058 Host_Error("R_UpdateTexture: no texture supplied");
3059 if (!glt->texnum && !glt->d3dtexture)
3061 Con_DPrintf("R_UpdateTexture: texture %p \"%s\" in pool %p has not been uploaded yet\n", (void *)glt, glt->identifier, (void *)glt->pool);
3064 // update part of the texture
3065 if (glt->bufferpixels)
3068 int bpp = glt->bytesperpixel;
3069 int inputskip = width*bpp;
3070 int outputskip = glt->tilewidth*bpp;
3071 const unsigned char *input = data;
3072 unsigned char *output = glt->bufferpixels;
3073 if (glt->inputdepth != 1 || glt->sides != 1)
3074 Sys_Error("R_UpdateTexture on buffered texture that is not 2D\n");
3084 input -= y*inputskip;
3087 if (width > glt->tilewidth - x)
3088 width = glt->tilewidth - x;
3089 if (height > glt->tileheight - y)
3090 height = glt->tileheight - y;
3091 if (width < 1 || height < 1)
3094 glt->buffermodified = true;
3095 output += y*outputskip + x*bpp;
3096 for (j = 0;j < height;j++, output += outputskip, input += inputskip)
3097 memcpy(output, input, width*bpp);
3099 else if (x || y || z || width != glt->inputwidth || height != glt->inputheight || depth != glt->inputdepth)
3100 R_UploadPartialTexture(glt, data, x, y, z, width, height, depth);
3102 R_UploadFullTexture(glt, data);
3105 int R_RealGetTexture(rtexture_t *rt)
3110 glt = (gltexture_t *)rt;
3111 if (glt->flags & GLTEXF_DYNAMIC)
3112 R_UpdateDynamicTexture(glt);
3113 if (glt->buffermodified && glt->bufferpixels)
3115 glt->buffermodified = false;
3116 R_UploadFullTexture(glt, glt->bufferpixels);
3125 void R_ClearTexture (rtexture_t *rt)
3127 gltexture_t *glt = (gltexture_t *)rt;
3129 R_UploadFullTexture(glt, NULL);
3132 int R_PicmipForFlags(int flags)
3135 if(flags & TEXF_PICMIP)
3137 miplevel += gl_picmip.integer;
3138 if (flags & TEXF_ISWORLD)
3140 if (r_picmipworld.integer)
3141 miplevel += gl_picmip_world.integer;
3145 else if (flags & TEXF_ISSPRITE)
3147 if (r_picmipsprites.integer)
3148 miplevel += gl_picmip_sprites.integer;
3153 miplevel += gl_picmip_other.integer;
3155 return max(0, miplevel);