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_RGBA16F , GL_RGBA , GL_HALF_FLOAT_ARB};
100 static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F , 2, 2, 2.0f, GL_RGBA32F , GL_RGBA , GL_FLOAT};
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_HALF_FLOAT_ARB};
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 *updatecallback_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->updatecallback_data = data;
359 static void R_UpdateDynamicTexture(gltexture_t *glt) {
361 if( glt->updatecallback ) {
362 glt->updatecallback( (rtexture_t*) glt, glt->updatecallback_data );
366 void R_PurgeTexture(rtexture_t *rt)
368 if(rt && !(((gltexture_t*) rt)->flags & TEXF_PERSISTENT)) {
373 void R_FreeTexture(rtexture_t *rt)
375 gltexture_t *glt, **gltpointer;
377 glt = (gltexture_t *)rt;
379 Host_Error("R_FreeTexture: texture == NULL");
381 for (gltpointer = &glt->pool->gltchain;*gltpointer && *gltpointer != glt;gltpointer = &(*gltpointer)->chain);
382 if (*gltpointer == glt)
383 *gltpointer = glt->chain;
385 Host_Error("R_FreeTexture: texture \"%s\" not linked in pool", glt->identifier);
387 R_Mesh_ClearBindingsForTexture(glt->texnum);
389 switch(vid.renderpath)
391 case RENDERPATH_GL11:
392 case RENDERPATH_GL13:
393 case RENDERPATH_GL20:
394 case RENDERPATH_GLES1:
395 case RENDERPATH_GLES2:
399 qglDeleteTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
401 if (glt->renderbuffernum)
404 qglDeleteRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR
407 case RENDERPATH_D3D9:
410 IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dsurface);
411 else if (glt->tiledepth > 1)
412 IDirect3DVolumeTexture9_Release((IDirect3DVolumeTexture9 *)glt->d3dtexture);
413 else if (glt->sides == 6)
414 IDirect3DCubeTexture9_Release((IDirect3DCubeTexture9 *)glt->d3dtexture);
416 IDirect3DTexture9_Release((IDirect3DTexture9 *)glt->d3dtexture);
417 glt->d3dtexture = NULL;
418 glt->d3dsurface = NULL;
421 case RENDERPATH_D3D10:
422 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
424 case RENDERPATH_D3D11:
425 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
427 case RENDERPATH_SOFT:
429 DPSOFTRAST_Texture_Free(glt->texnum);
433 if (glt->inputtexels)
434 Mem_Free(glt->inputtexels);
435 Mem_ExpandableArray_FreeRecord(&texturearray, glt);
438 rtexturepool_t *R_AllocTexturePool(void)
440 gltexturepool_t *pool;
441 if (texturemempool == NULL)
443 pool = (gltexturepool_t *)Mem_Alloc(texturemempool, sizeof(gltexturepool_t));
446 pool->next = gltexturepoolchain;
447 gltexturepoolchain = pool;
448 pool->sentinel = TEXTUREPOOL_SENTINEL;
449 return (rtexturepool_t *)pool;
452 void R_FreeTexturePool(rtexturepool_t **rtexturepool)
454 gltexturepool_t *pool, **poolpointer;
455 if (rtexturepool == NULL)
457 if (*rtexturepool == NULL)
459 pool = (gltexturepool_t *)(*rtexturepool);
460 *rtexturepool = NULL;
461 if (pool->sentinel != TEXTUREPOOL_SENTINEL)
462 Host_Error("R_FreeTexturePool: pool already freed");
463 for (poolpointer = &gltexturepoolchain;*poolpointer && *poolpointer != pool;poolpointer = &(*poolpointer)->next);
464 if (*poolpointer == pool)
465 *poolpointer = pool->next;
467 Host_Error("R_FreeTexturePool: pool not linked");
468 while (pool->gltchain)
469 R_FreeTexture((rtexture_t *)pool->gltchain);
474 typedef struct glmode_s
477 int minification, magnification;
478 DPSOFTRAST_TEXTURE_FILTER dpsoftrastfilter_mipmap, dpsoftrastfilter_nomipmap;
482 static glmode_t modes[6] =
484 {"GL_NEAREST", GL_NEAREST, GL_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST},
485 {"GL_LINEAR", GL_LINEAR, GL_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR},
486 {"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_NEAREST},
487 {"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_LINEAR},
488 {"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST, DPSOFTRAST_TEXTURE_FILTER_NEAREST_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_NEAREST},
489 {"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, DPSOFTRAST_TEXTURE_FILTER_LINEAR_MIPMAP_TRIANGLE, DPSOFTRAST_TEXTURE_FILTER_LINEAR}
493 typedef struct d3dmode_s
500 static d3dmode_t d3dmodes[6] =
502 {"GL_NEAREST", D3DTEXF_POINT, D3DTEXF_POINT},
503 {"GL_LINEAR", D3DTEXF_LINEAR, D3DTEXF_POINT},
504 {"GL_NEAREST_MIPMAP_NEAREST", D3DTEXF_POINT, D3DTEXF_POINT},
505 {"GL_LINEAR_MIPMAP_NEAREST", D3DTEXF_LINEAR, D3DTEXF_POINT},
506 {"GL_NEAREST_MIPMAP_LINEAR", D3DTEXF_POINT, D3DTEXF_LINEAR},
507 {"GL_LINEAR_MIPMAP_LINEAR", D3DTEXF_LINEAR, D3DTEXF_LINEAR}
511 static void GL_TextureMode_f (void)
516 gltexturepool_t *pool;
520 Con_Printf("Texture mode is %sforced\n", gl_filter_force ? "" : "not ");
521 for (i = 0;i < 6;i++)
523 if (gl_filter_min == modes[i].minification)
525 Con_Printf("%s\n", modes[i].name);
529 Con_Print("current filter is unknown???\n");
533 for (i = 0;i < (int)(sizeof(modes)/sizeof(*modes));i++)
534 if (!strcasecmp (modes[i].name, Cmd_Argv(1) ) )
538 Con_Print("bad filter name\n");
542 gl_filter_min = modes[i].minification;
543 gl_filter_mag = modes[i].magnification;
544 gl_filter_force = ((Cmd_Argc() > 2) && !strcasecmp(Cmd_Argv(2), "force"));
546 dpsoftrast_filter_mipmap = modes[i].dpsoftrastfilter_mipmap;
547 dpsoftrast_filter_nomipmap = modes[i].dpsoftrastfilter_nomipmap;
549 switch(vid.renderpath)
551 case RENDERPATH_GL11:
552 case RENDERPATH_GL13:
553 case RENDERPATH_GL20:
554 case RENDERPATH_GLES1:
555 case RENDERPATH_GLES2:
556 // change all the existing mipmap texture objects
557 // FIXME: force renderer(/client/something?) restart instead?
560 for (pool = gltexturepoolchain;pool;pool = pool->next)
562 for (glt = pool->gltchain;glt;glt = glt->chain)
564 // only update already uploaded images
565 if (glt->texnum && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
567 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
568 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
569 if (glt->flags & TEXF_MIPMAP)
571 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_min);CHECKGLERROR
575 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_mag);CHECKGLERROR
577 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR
578 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
583 case RENDERPATH_D3D9:
585 d3d_filter_flatmin = d3dmodes[i].m1;
586 d3d_filter_flatmag = d3dmodes[i].m1;
587 d3d_filter_flatmix = D3DTEXF_POINT;
588 d3d_filter_mipmin = d3dmodes[i].m1;
589 d3d_filter_mipmag = d3dmodes[i].m1;
590 d3d_filter_mipmix = d3dmodes[i].m2;
591 d3d_filter_nomip = i < 2;
592 if (gl_texture_anisotropy.integer > 1 && i == 5)
593 d3d_filter_mipmin = d3d_filter_mipmag = D3DTEXF_ANISOTROPIC;
594 for (pool = gltexturepoolchain;pool;pool = pool->next)
596 for (glt = pool->gltchain;glt;glt = glt->chain)
598 // only update already uploaded images
599 if (glt->d3dtexture && !glt->d3dsurface && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
601 if (glt->flags & TEXF_MIPMAP)
603 glt->d3dminfilter = d3d_filter_mipmin;
604 glt->d3dmagfilter = d3d_filter_mipmag;
605 glt->d3dmipfilter = d3d_filter_mipmix;
606 glt->d3dmaxmiplevelfilter = 0;
610 glt->d3dminfilter = d3d_filter_flatmin;
611 glt->d3dmagfilter = d3d_filter_flatmag;
612 glt->d3dmipfilter = d3d_filter_flatmix;
613 glt->d3dmaxmiplevelfilter = 0;
620 case RENDERPATH_D3D10:
621 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
623 case RENDERPATH_D3D11:
624 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
626 case RENDERPATH_SOFT:
627 // change all the existing texture objects
628 for (pool = gltexturepoolchain;pool;pool = pool->next)
629 for (glt = pool->gltchain;glt;glt = glt->chain)
630 if (glt->texnum && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
631 DPSOFTRAST_Texture_Filter(glt->texnum, (glt->flags & TEXF_MIPMAP) ? dpsoftrast_filter_mipmap : dpsoftrast_filter_nomipmap);
636 static void GL_Texture_CalcImageSize(int texturetype, int flags, int miplevel, int inwidth, int inheight, int indepth, int *outwidth, int *outheight, int *outdepth, int *outmiplevels)
638 int picmip = 0, maxsize = 0, width2 = 1, height2 = 1, depth2 = 1, miplevels = 1;
643 case GLTEXTURETYPE_2D:
644 maxsize = vid.maxtexturesize_2d;
645 if (flags & TEXF_PICMIP)
647 maxsize = bound(1, gl_max_size.integer, maxsize);
651 case GLTEXTURETYPE_3D:
652 maxsize = vid.maxtexturesize_3d;
654 case GLTEXTURETYPE_CUBEMAP:
655 maxsize = vid.maxtexturesize_cubemap;
659 if (vid.support.arb_texture_non_power_of_two)
661 width2 = min(inwidth >> picmip, maxsize);
662 height2 = min(inheight >> picmip, maxsize);
663 depth2 = min(indepth >> picmip, maxsize);
667 for (width2 = 1;width2 < inwidth;width2 <<= 1);
668 for (width2 >>= picmip;width2 > maxsize;width2 >>= 1);
669 for (height2 = 1;height2 < inheight;height2 <<= 1);
670 for (height2 >>= picmip;height2 > maxsize;height2 >>= 1);
671 for (depth2 = 1;depth2 < indepth;depth2 <<= 1);
672 for (depth2 >>= picmip;depth2 > maxsize;depth2 >>= 1);
675 switch(vid.renderpath)
677 case RENDERPATH_GL11:
678 case RENDERPATH_GL13:
679 case RENDERPATH_GL20:
680 case RENDERPATH_D3D10:
681 case RENDERPATH_D3D11:
682 case RENDERPATH_SOFT:
683 case RENDERPATH_GLES1:
684 case RENDERPATH_GLES2:
686 case RENDERPATH_D3D9:
688 // for some reason the REF rasterizer (and hence the PIX debugger) does not like small textures...
689 if (texturetype == GLTEXTURETYPE_2D)
691 width2 = max(width2, 2);
692 height2 = max(height2, 2);
699 if (flags & TEXF_MIPMAP)
701 int extent = max(width2, max(height2, depth2));
707 *outwidth = max(1, width2);
709 *outheight = max(1, height2);
711 *outdepth = max(1, depth2);
713 *outmiplevels = miplevels;
717 static int R_CalcTexelDataSize (gltexture_t *glt)
719 int width2, height2, depth2, size;
721 GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &width2, &height2, &depth2, NULL);
723 size = width2 * height2 * depth2;
725 if (glt->flags & TEXF_MIPMAP)
727 while (width2 > 1 || height2 > 1 || depth2 > 1)
735 size += width2 * height2 * depth2;
739 return (int)(size * glt->textype->glinternalbytesperpixel) * glt->sides;
742 void R_TextureStats_Print(qboolean printeach, qboolean printpool, qboolean printtotal)
746 int pooltotal = 0, pooltotalt = 0, pooltotalp = 0, poolloaded = 0, poolloadedt = 0, poolloadedp = 0;
747 int sumtotal = 0, sumtotalt = 0, sumtotalp = 0, sumloaded = 0, sumloadedt = 0, sumloadedp = 0;
749 gltexturepool_t *pool;
751 Con_Print("glsize input loaded mip alpha name\n");
752 for (pool = gltexturepoolchain;pool;pool = pool->next)
760 for (glt = pool->gltchain;glt;glt = glt->chain)
762 glsize = R_CalcTexelDataSize(glt);
763 isloaded = glt->texnum != 0 || glt->renderbuffernum != 0 || glt->d3dtexture || glt->d3dsurface;
765 pooltotalt += glsize;
766 pooltotalp += glt->inputdatasize;
770 poolloadedt += glsize;
771 poolloadedp += glt->inputdatasize;
774 Con_Printf("%c%4i%c%c%4i%c %-24s %s %s %s %s\n", isloaded ? '[' : ' ', (glsize + 1023) / 1024, isloaded ? ']' : ' ', glt->inputtexels ? '[' : ' ', (glt->inputdatasize + 1023) / 1024, glt->inputtexels ? ']' : ' ', glt->textype->name, isloaded ? "loaded" : " ", (glt->flags & TEXF_MIPMAP) ? "mip" : " ", (glt->flags & TEXF_ALPHA) ? "alpha" : " ", glt->identifier);
777 Con_Printf("texturepool %10p total: %i (%.3fMB, %.3fMB original), uploaded %i (%.3fMB, %.3fMB original), upload on demand %i (%.3fMB, %.3fMB original)\n", (void *)pool, pooltotal, pooltotalt / 1048576.0, pooltotalp / 1048576.0, poolloaded, poolloadedt / 1048576.0, poolloadedp / 1048576.0, pooltotal - poolloaded, (pooltotalt - poolloadedt) / 1048576.0, (pooltotalp - poolloadedp) / 1048576.0);
778 sumtotal += pooltotal;
779 sumtotalt += pooltotalt;
780 sumtotalp += pooltotalp;
781 sumloaded += poolloaded;
782 sumloadedt += poolloadedt;
783 sumloadedp += poolloadedp;
786 Con_Printf("textures total: %i (%.3fMB, %.3fMB original), uploaded %i (%.3fMB, %.3fMB original), upload on demand %i (%.3fMB, %.3fMB original)\n", sumtotal, sumtotalt / 1048576.0, sumtotalp / 1048576.0, sumloaded, sumloadedt / 1048576.0, sumloadedp / 1048576.0, sumtotal - sumloaded, (sumtotalt - sumloadedt) / 1048576.0, (sumtotalp - sumloadedp) / 1048576.0);
789 static void R_TextureStats_f(void)
791 R_TextureStats_Print(true, true, true);
794 static void r_textures_start(void)
796 switch(vid.renderpath)
798 case RENDERPATH_GL11:
799 case RENDERPATH_GL13:
800 case RENDERPATH_GL20:
801 case RENDERPATH_GLES1:
802 case RENDERPATH_GLES2:
803 // LordHavoc: allow any alignment
805 qglPixelStorei(GL_UNPACK_ALIGNMENT, 1);CHECKGLERROR
806 qglPixelStorei(GL_PACK_ALIGNMENT, 1);CHECKGLERROR
808 case RENDERPATH_D3D9:
810 case RENDERPATH_D3D10:
811 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
813 case RENDERPATH_D3D11:
814 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
816 case RENDERPATH_SOFT:
820 texturemempool = Mem_AllocPool("texture management", 0, NULL);
821 Mem_ExpandableArray_NewArray(&texturearray, texturemempool, sizeof(gltexture_t), 512);
823 // Disable JPEG screenshots if the DLL isn't loaded
824 if (! JPEG_OpenLibrary ())
825 Cvar_SetValueQuick (&scr_screenshot_jpeg, 0);
826 if (! PNG_OpenLibrary ())
827 Cvar_SetValueQuick (&scr_screenshot_png, 0);
830 static void r_textures_shutdown(void)
832 rtexturepool_t *temp;
834 JPEG_CloseLibrary ();
836 while(gltexturepoolchain)
838 temp = (rtexturepool_t *) gltexturepoolchain;
839 R_FreeTexturePool(&temp);
842 resizebuffersize = 0;
844 colorconvertbuffer = NULL;
845 texturebuffer = NULL;
846 Mem_ExpandableArray_FreeArray(&texturearray);
847 Mem_FreePool(&texturemempool);
850 static void r_textures_newmap(void)
854 static void r_textures_devicelost(void)
858 endindex = (int)Mem_ExpandableArray_IndexRange(&texturearray);
859 for (i = 0;i < endindex;i++)
861 glt = (gltexture_t *) Mem_ExpandableArray_RecordAtIndex(&texturearray, i);
862 if (!glt || !(glt->flags & TEXF_RENDERTARGET))
864 switch(vid.renderpath)
866 case RENDERPATH_GL11:
867 case RENDERPATH_GL13:
868 case RENDERPATH_GL20:
869 case RENDERPATH_GLES1:
870 case RENDERPATH_GLES2:
872 case RENDERPATH_D3D9:
875 IDirect3DSurface9_Release((IDirect3DSurface9 *)glt->d3dsurface);
876 else if (glt->tiledepth > 1)
877 IDirect3DVolumeTexture9_Release((IDirect3DVolumeTexture9 *)glt->d3dtexture);
878 else if (glt->sides == 6)
879 IDirect3DCubeTexture9_Release((IDirect3DCubeTexture9 *)glt->d3dtexture);
881 IDirect3DTexture9_Release((IDirect3DTexture9 *)glt->d3dtexture);
882 glt->d3dtexture = NULL;
883 glt->d3dsurface = NULL;
886 case RENDERPATH_D3D10:
887 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
889 case RENDERPATH_D3D11:
890 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
892 case RENDERPATH_SOFT:
898 static void r_textures_devicerestored(void)
902 endindex = (int)Mem_ExpandableArray_IndexRange(&texturearray);
903 for (i = 0;i < endindex;i++)
905 glt = (gltexture_t *) Mem_ExpandableArray_RecordAtIndex(&texturearray, i);
906 if (!glt || !(glt->flags & TEXF_RENDERTARGET))
908 switch(vid.renderpath)
910 case RENDERPATH_GL11:
911 case RENDERPATH_GL13:
912 case RENDERPATH_GL20:
913 case RENDERPATH_GLES1:
914 case RENDERPATH_GLES2:
916 case RENDERPATH_D3D9:
920 if (glt->d3disrendertargetsurface)
922 if (FAILED(d3dresult = IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
923 Sys_Error("IDirect3DDevice9_CreateRenderTarget failed!");
925 else if (glt->d3disdepthstencilsurface)
927 if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
928 Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
930 else if (glt->tiledepth > 1)
932 if (FAILED(d3dresult = IDirect3DDevice9_CreateVolumeTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->tiledepth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DVolumeTexture9 **)&glt->d3dtexture, NULL)))
933 Sys_Error("IDirect3DDevice9_CreateVolumeTexture failed!");
935 else if (glt->sides == 6)
937 if (FAILED(d3dresult = IDirect3DDevice9_CreateCubeTexture(vid_d3d9dev, glt->tilewidth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DCubeTexture9 **)&glt->d3dtexture, NULL)))
938 Sys_Error("IDirect3DDevice9_CreateCubeTexture failed!");
942 if (FAILED(d3dresult = IDirect3DDevice9_CreateTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DTexture9 **)&glt->d3dtexture, NULL)))
943 Sys_Error("IDirect3DDevice9_CreateTexture failed!");
948 case RENDERPATH_D3D10:
949 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
951 case RENDERPATH_D3D11:
952 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
954 case RENDERPATH_SOFT:
961 void R_Textures_Init (void)
963 Cmd_AddCommand("gl_texturemode", &GL_TextureMode_f, "set texture filtering mode (GL_NEAREST, GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, etc); an additional argument 'force' forces the texture mode even in cases where it may not be appropriate");
964 Cmd_AddCommand("r_texturestats", R_TextureStats_f, "print information about all loaded textures and some statistics");
965 Cvar_RegisterVariable (&gl_max_size);
966 Cvar_RegisterVariable (&gl_picmip);
967 Cvar_RegisterVariable (&gl_picmip_world);
968 Cvar_RegisterVariable (&r_picmipworld);
969 Cvar_RegisterVariable (&gl_picmip_sprites);
970 Cvar_RegisterVariable (&r_picmipsprites);
971 Cvar_RegisterVariable (&gl_picmip_other);
972 Cvar_RegisterVariable (&gl_max_lightmapsize);
973 Cvar_RegisterVariable (&r_lerpimages);
974 Cvar_RegisterVariable (&gl_texture_anisotropy);
975 Cvar_RegisterVariable (&gl_texturecompression);
976 Cvar_RegisterVariable (&gl_texturecompression_color);
977 Cvar_RegisterVariable (&gl_texturecompression_normal);
978 Cvar_RegisterVariable (&gl_texturecompression_gloss);
979 Cvar_RegisterVariable (&gl_texturecompression_glow);
980 Cvar_RegisterVariable (&gl_texturecompression_2d);
981 Cvar_RegisterVariable (&gl_texturecompression_q3bsplightmaps);
982 Cvar_RegisterVariable (&gl_texturecompression_q3bspdeluxemaps);
983 Cvar_RegisterVariable (&gl_texturecompression_sky);
984 Cvar_RegisterVariable (&gl_texturecompression_lightcubemaps);
985 Cvar_RegisterVariable (&gl_texturecompression_reflectmask);
986 Cvar_RegisterVariable (&gl_texturecompression_sprites);
987 Cvar_RegisterVariable (&gl_nopartialtextureupdates);
988 Cvar_RegisterVariable (&r_texture_dds_load_alphamode);
989 Cvar_RegisterVariable (&r_texture_dds_load_logfailure);
990 Cvar_RegisterVariable (&r_texture_dds_swdecode);
992 R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown, r_textures_newmap, r_textures_devicelost, r_textures_devicerestored);
995 void R_Textures_Frame (void)
997 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
998 static int old_aniso = 0;
1001 // could do procedural texture animation here, if we keep track of which
1002 // textures were accessed this frame...
1004 // free the resize buffers
1005 resizebuffersize = 0;
1008 Mem_Free(resizebuffer);
1009 resizebuffer = NULL;
1011 if (colorconvertbuffer)
1013 Mem_Free(colorconvertbuffer);
1014 colorconvertbuffer = NULL;
1017 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1018 if (old_aniso != gl_texture_anisotropy.integer)
1021 gltexturepool_t *pool;
1022 GLint oldbindtexnum;
1024 old_aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
1026 Cvar_SetValueQuick(&gl_texture_anisotropy, old_aniso);
1028 switch(vid.renderpath)
1030 case RENDERPATH_GL11:
1031 case RENDERPATH_GL13:
1032 case RENDERPATH_GL20:
1033 case RENDERPATH_GLES1:
1034 case RENDERPATH_GLES2:
1036 GL_ActiveTexture(0);
1037 for (pool = gltexturepoolchain;pool;pool = pool->next)
1039 for (glt = pool->gltchain;glt;glt = glt->chain)
1041 // only update already uploaded images
1042 if (glt->texnum && (glt->flags & TEXF_MIPMAP) == TEXF_MIPMAP)
1044 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
1046 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
1047 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_ANISOTROPY_EXT, old_aniso);CHECKGLERROR
1049 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
1054 case RENDERPATH_D3D9:
1055 case RENDERPATH_D3D10:
1056 case RENDERPATH_D3D11:
1057 case RENDERPATH_SOFT:
1064 static void R_MakeResizeBufferBigger(int size)
1066 if (resizebuffersize < size)
1068 resizebuffersize = size;
1070 Mem_Free(resizebuffer);
1071 if (colorconvertbuffer)
1072 Mem_Free(colorconvertbuffer);
1073 resizebuffer = (unsigned char *)Mem_Alloc(texturemempool, resizebuffersize);
1074 colorconvertbuffer = (unsigned char *)Mem_Alloc(texturemempool, resizebuffersize);
1075 if (!resizebuffer || !colorconvertbuffer)
1076 Host_Error("R_Upload: out of memory");
1080 static void GL_SetupTextureParameters(int flags, textype_t textype, int texturetype)
1082 int textureenum = gltexturetypeenums[texturetype];
1083 int wrapmode = (flags & TEXF_CLAMP) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
1087 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1088 if (vid.support.ext_texture_filter_anisotropic && (flags & TEXF_MIPMAP))
1090 int aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
1091 if (gl_texture_anisotropy.integer != aniso)
1092 Cvar_SetValueQuick(&gl_texture_anisotropy, aniso);
1093 qglTexParameteri(textureenum, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);CHECKGLERROR
1096 qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode);CHECKGLERROR
1097 qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode);CHECKGLERROR
1098 #ifdef GL_TEXTURE_WRAP_R
1099 if (gltexturetypedimensions[texturetype] >= 3)
1101 qglTexParameteri(textureenum, GL_TEXTURE_WRAP_R, wrapmode);CHECKGLERROR
1106 if (!gl_filter_force && flags & TEXF_FORCENEAREST)
1108 if (flags & TEXF_MIPMAP)
1110 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);CHECKGLERROR
1114 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_NEAREST);CHECKGLERROR
1116 qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, GL_NEAREST);CHECKGLERROR
1118 else if (!gl_filter_force && flags & TEXF_FORCELINEAR)
1120 if (flags & TEXF_MIPMAP)
1122 if (gl_filter_min == GL_NEAREST_MIPMAP_LINEAR || gl_filter_min == GL_LINEAR_MIPMAP_LINEAR)
1124 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);CHECKGLERROR
1128 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);CHECKGLERROR
1133 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_LINEAR);CHECKGLERROR
1135 qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, GL_LINEAR);CHECKGLERROR
1139 if (flags & TEXF_MIPMAP)
1141 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_min);CHECKGLERROR
1145 qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_mag);CHECKGLERROR
1147 qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR
1150 #ifdef GL_TEXTURE_COMPARE_MODE_ARB
1153 case TEXTYPE_SHADOWMAP16_COMP:
1154 case TEXTYPE_SHADOWMAP24_COMP:
1155 qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
1156 qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
1157 qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
1159 case TEXTYPE_SHADOWMAP16_RAW:
1160 case TEXTYPE_SHADOWMAP24_RAW:
1161 qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
1162 qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
1163 qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
1173 static void R_UploadPartialTexture(gltexture_t *glt, const unsigned char *data, int fragx, int fragy, int fragz, int fragwidth, int fragheight, int fragdepth)
1176 Sys_Error("R_UploadPartialTexture \"%s\": partial update with NULL pixels", glt->identifier);
1178 if (glt->texturetype != GLTEXTURETYPE_2D)
1179 Sys_Error("R_UploadPartialTexture \"%s\": partial update of type other than 2D", glt->identifier);
1181 if (glt->textype->textype == TEXTYPE_PALETTE)
1182 Sys_Error("R_UploadPartialTexture \"%s\": partial update of paletted texture", glt->identifier);
1184 if (glt->flags & (TEXF_MIPMAP | TEXF_PICMIP))
1185 Sys_Error("R_UploadPartialTexture \"%s\": partial update not supported with MIPMAP or PICMIP flags", glt->identifier);
1187 if (glt->inputwidth != glt->tilewidth || glt->inputheight != glt->tileheight || glt->tiledepth != 1)
1188 Sys_Error("R_UploadPartialTexture \"%s\": partial update not supported with stretched or special textures", glt->identifier);
1190 // update a portion of the image
1192 switch(vid.renderpath)
1194 case RENDERPATH_GL11:
1195 case RENDERPATH_GL13:
1196 case RENDERPATH_GL20:
1197 case RENDERPATH_GLES1:
1198 case RENDERPATH_GLES2:
1202 // we need to restore the texture binding after finishing the upload
1203 GL_ActiveTexture(0);
1204 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
1205 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
1206 qglTexSubImage2D(GL_TEXTURE_2D, 0, fragx, fragy, fragwidth, fragheight, glt->glformat, glt->gltype, data);CHECKGLERROR
1207 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
1210 case RENDERPATH_D3D9:
1214 D3DLOCKED_RECT d3dlockedrect;
1216 memset(&d3drect, 0, sizeof(d3drect));
1217 d3drect.left = fragx;
1218 d3drect.top = fragy;
1219 d3drect.right = fragx+fragwidth;
1220 d3drect.bottom = fragy+fragheight;
1221 if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, 0, &d3dlockedrect, &d3drect, 0) == D3D_OK && d3dlockedrect.pBits)
1223 for (y = 0;y < fragheight;y++)
1224 memcpy((unsigned char *)d3dlockedrect.pBits + d3dlockedrect.Pitch * y, data + fragwidth*glt->bytesperpixel * y, fragwidth*glt->bytesperpixel);
1225 IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, 0);
1230 case RENDERPATH_D3D10:
1231 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1233 case RENDERPATH_D3D11:
1234 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1236 case RENDERPATH_SOFT:
1237 DPSOFTRAST_Texture_UpdatePartial(glt->texnum, 0, data, fragx, fragy, fragwidth, fragheight);
1242 static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data)
1244 int i, mip = 0, width, height, depth;
1245 GLint oldbindtexnum = 0;
1246 const unsigned char *prevbuffer;
1249 // error out if a stretch is needed on special texture types
1250 if (glt->texturetype != GLTEXTURETYPE_2D && (glt->tilewidth != glt->inputwidth || glt->tileheight != glt->inputheight || glt->tiledepth != glt->inputdepth))
1251 Sys_Error("R_UploadFullTexture \"%s\": stretch uploads allowed only on 2D textures\n", glt->identifier);
1253 // when picmip or maxsize is applied, we scale up to a power of 2 multiple
1254 // of the target size and then use the mipmap reduction function to get
1255 // high quality supersampled results
1256 for (width = glt->tilewidth;width < glt->inputwidth ;width <<= 1);
1257 for (height = glt->tileheight;height < glt->inputheight;height <<= 1);
1258 for (depth = glt->tiledepth;depth < glt->inputdepth ;depth <<= 1);
1260 if (prevbuffer == NULL)
1262 width = glt->tilewidth;
1263 height = glt->tileheight;
1264 depth = glt->tiledepth;
1265 // R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
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 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1275 Image_Copy8bitBGRA(prevbuffer, colorconvertbuffer, glt->inputwidth * glt->inputheight * glt->inputdepth * glt->sides, glt->palette);
1276 prevbuffer = colorconvertbuffer;
1278 if (glt->flags & TEXF_RGBMULTIPLYBYALPHA)
1280 // multiply RGB channels by A channel before uploading
1282 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1283 for (i = 0;i < glt->inputwidth*glt->inputheight*glt->inputdepth*4;i += 4)
1285 alpha = prevbuffer[i+3];
1286 colorconvertbuffer[i] = (prevbuffer[i] * alpha) >> 8;
1287 colorconvertbuffer[i+1] = (prevbuffer[i+1] * alpha) >> 8;
1288 colorconvertbuffer[i+2] = (prevbuffer[i+2] * alpha) >> 8;
1289 colorconvertbuffer[i+3] = alpha;
1291 prevbuffer = colorconvertbuffer;
1293 // scale up to a power of 2 size (if appropriate)
1294 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1296 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1297 Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1298 prevbuffer = resizebuffer;
1300 // apply mipmap reduction algorithm to get down to picmip/max_size
1301 while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1303 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1304 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1305 prevbuffer = resizebuffer;
1309 // do the appropriate upload type...
1310 switch(vid.renderpath)
1312 case RENDERPATH_GL11:
1313 case RENDERPATH_GL13:
1314 case RENDERPATH_GL20:
1315 case RENDERPATH_GLES1:
1316 case RENDERPATH_GLES2:
1317 if (glt->texnum) // not renderbuffers
1321 // we need to restore the texture binding after finishing the upload
1322 GL_ActiveTexture(0);
1323 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
1324 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
1327 #ifdef GL_TEXTURE_COMPRESSION_HINT_ARB
1328 if (qglGetCompressedTexImageARB)
1330 if (gl_texturecompression.integer >= 2)
1331 qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
1333 qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_FASTEST);
1338 switch(glt->texturetype)
1340 case GLTEXTURETYPE_2D:
1341 qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1342 if (glt->flags & TEXF_MIPMAP)
1344 while (width > 1 || height > 1 || depth > 1)
1346 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1347 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1348 prevbuffer = resizebuffer;
1349 qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1353 case GLTEXTURETYPE_3D:
1355 qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1356 if (glt->flags & TEXF_MIPMAP)
1358 while (width > 1 || height > 1 || depth > 1)
1360 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1361 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1362 prevbuffer = resizebuffer;
1363 qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1368 case GLTEXTURETYPE_CUBEMAP:
1369 // convert and upload each side in turn,
1370 // from a continuous block of input texels
1371 texturebuffer = (unsigned char *)prevbuffer;
1372 for (i = 0;i < 6;i++)
1374 prevbuffer = texturebuffer;
1375 texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
1376 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1378 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1379 Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1380 prevbuffer = resizebuffer;
1383 while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1385 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1386 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1387 prevbuffer = resizebuffer;
1390 qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1391 if (glt->flags & TEXF_MIPMAP)
1393 while (width > 1 || height > 1 || depth > 1)
1395 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1396 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1397 prevbuffer = resizebuffer;
1398 qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1404 GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
1405 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
1408 case RENDERPATH_D3D9:
1410 if (!(glt->flags & TEXF_RENDERTARGET) && glt->d3dtexture && !glt->d3dsurface)
1412 D3DLOCKED_RECT d3dlockedrect;
1413 D3DLOCKED_BOX d3dlockedbox;
1414 switch(glt->texturetype)
1416 case GLTEXTURETYPE_2D:
1417 if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1420 memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1422 memset(d3dlockedrect.pBits, 255, width*height*glt->bytesperpixel);
1423 IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
1426 if ((glt->flags & TEXF_MIPMAP) && prevbuffer)
1428 while (width > 1 || height > 1 || depth > 1)
1430 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1431 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1432 prevbuffer = resizebuffer;
1433 if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1435 memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1436 IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
1442 case GLTEXTURETYPE_3D:
1443 if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits)
1445 // we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes
1446 memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel);
1447 IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip);
1450 if (glt->flags & TEXF_MIPMAP)
1452 while (width > 1 || height > 1 || depth > 1)
1454 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1455 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1456 prevbuffer = resizebuffer;
1457 if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits)
1459 // we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes
1460 memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel);
1461 IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip);
1467 case GLTEXTURETYPE_CUBEMAP:
1468 // convert and upload each side in turn,
1469 // from a continuous block of input texels
1470 texturebuffer = (unsigned char *)prevbuffer;
1471 for (i = 0;i < 6;i++)
1473 prevbuffer = texturebuffer;
1474 texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
1475 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1477 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1478 Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1479 prevbuffer = resizebuffer;
1482 while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1484 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1485 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1486 prevbuffer = resizebuffer;
1489 if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1491 memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1492 IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip);
1495 if (glt->flags & TEXF_MIPMAP)
1497 while (width > 1 || height > 1 || depth > 1)
1499 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1500 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1501 prevbuffer = resizebuffer;
1502 if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1504 memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1505 IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip);
1514 glt->d3daddressw = 0;
1515 if (glt->flags & TEXF_CLAMP)
1517 glt->d3daddressu = D3DTADDRESS_CLAMP;
1518 glt->d3daddressv = D3DTADDRESS_CLAMP;
1519 if (glt->tiledepth > 1)
1520 glt->d3daddressw = D3DTADDRESS_CLAMP;
1524 glt->d3daddressu = D3DTADDRESS_WRAP;
1525 glt->d3daddressv = D3DTADDRESS_WRAP;
1526 if (glt->tiledepth > 1)
1527 glt->d3daddressw = D3DTADDRESS_WRAP;
1529 glt->d3dmipmaplodbias = 0;
1530 glt->d3dmaxmiplevel = 0;
1531 glt->d3dmaxmiplevelfilter = d3d_filter_nomip ? 0 : glt->d3dmaxmiplevel;
1532 if (glt->flags & TEXF_FORCELINEAR)
1534 glt->d3dminfilter = D3DTEXF_LINEAR;
1535 glt->d3dmagfilter = D3DTEXF_LINEAR;
1536 glt->d3dmipfilter = D3DTEXF_POINT;
1538 else if (glt->flags & TEXF_FORCENEAREST)
1540 glt->d3dminfilter = D3DTEXF_POINT;
1541 glt->d3dmagfilter = D3DTEXF_POINT;
1542 glt->d3dmipfilter = D3DTEXF_POINT;
1544 else if (glt->flags & TEXF_MIPMAP)
1546 glt->d3dminfilter = d3d_filter_mipmin;
1547 glt->d3dmagfilter = d3d_filter_mipmag;
1548 glt->d3dmipfilter = d3d_filter_mipmix;
1552 glt->d3dminfilter = d3d_filter_flatmin;
1553 glt->d3dmagfilter = d3d_filter_flatmag;
1554 glt->d3dmipfilter = d3d_filter_flatmix;
1558 case RENDERPATH_D3D10:
1559 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1561 case RENDERPATH_D3D11:
1562 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1564 case RENDERPATH_SOFT:
1565 switch(glt->texturetype)
1567 case GLTEXTURETYPE_2D:
1568 DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
1570 case GLTEXTURETYPE_3D:
1571 DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
1573 case GLTEXTURETYPE_CUBEMAP:
1574 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1576 unsigned char *combinedbuffer = (unsigned char *)Mem_Alloc(tempmempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
1577 // convert and upload each side in turn,
1578 // from a continuous block of input texels
1579 // copy the results into combinedbuffer
1580 texturebuffer = (unsigned char *)prevbuffer;
1581 for (i = 0;i < 6;i++)
1583 prevbuffer = texturebuffer;
1584 texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
1585 if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1587 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1588 Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1589 prevbuffer = resizebuffer;
1592 while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1594 R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1595 Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1596 prevbuffer = resizebuffer;
1598 memcpy(combinedbuffer + i*glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel, prevbuffer, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel);
1600 DPSOFTRAST_Texture_UpdateFull(glt->texnum, combinedbuffer);
1601 Mem_Free(combinedbuffer);
1604 DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
1607 if (glt->flags & TEXF_FORCELINEAR)
1608 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
1609 else if (glt->flags & TEXF_FORCENEAREST)
1610 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
1611 else if (glt->flags & TEXF_MIPMAP)
1612 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
1614 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
1619 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)
1623 gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
1624 textypeinfo_t *texinfo, *texinfo2;
1625 unsigned char *temppixels = NULL;
1628 if (cls.state == ca_dedicated)
1631 // see if we need to swap red and blue (BGRA <-> RGBA conversion)
1632 if (textype == TEXTYPE_PALETTE && vid.forcetextype == TEXTYPE_RGBA)
1634 int numpixels = width * height * depth * sides;
1635 size = numpixels * 4;
1636 temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
1639 const unsigned char *p;
1640 unsigned char *o = temppixels;
1641 for (i = 0;i < numpixels;i++, o += 4)
1643 p = (const unsigned char *)palette + 4*data[i];
1651 textype = TEXTYPE_RGBA;
1656 case TEXTYPE_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_BGRA;} break;
1657 case TEXTYPE_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_RGBA;} break;
1658 case TEXTYPE_SRGB_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_SRGB_BGRA;} break;
1659 case TEXTYPE_SRGB_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_SRGB_RGBA;} break;
1665 static int rgbaswapindices[4] = {2, 1, 0, 3};
1666 size = width * height * depth * sides * 4;
1667 temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
1669 Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices);
1673 // if sRGB texture formats are not supported, convert input to linear and upload as normal types
1674 if (!vid.support.ext_texture_srgb)
1676 qboolean convertsRGB = false;
1679 case TEXTYPE_SRGB_DXT1: textype = TEXTYPE_DXT1 ;convertsRGB = true;break;
1680 case TEXTYPE_SRGB_DXT1A: textype = TEXTYPE_DXT1A ;convertsRGB = true;break;
1681 case TEXTYPE_SRGB_DXT3: textype = TEXTYPE_DXT3 ;convertsRGB = true;break;
1682 case TEXTYPE_SRGB_DXT5: textype = TEXTYPE_DXT5 ;convertsRGB = true;break;
1683 case TEXTYPE_SRGB_PALETTE: textype = TEXTYPE_PALETTE;/*convertsRGB = true;*/break;
1684 case TEXTYPE_SRGB_RGBA: textype = TEXTYPE_RGBA ;convertsRGB = true;break;
1685 case TEXTYPE_SRGB_BGRA: textype = TEXTYPE_BGRA ;convertsRGB = true;break;
1689 if (convertsRGB && data)
1691 size = width * height * depth * sides * 4;
1694 temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
1695 memcpy(temppixels, data, size);
1698 Image_MakeLinearColorsFromsRGB(temppixels, temppixels, width*height*depth*sides);
1702 if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map)
1704 Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n");
1707 if (texturetype == GLTEXTURETYPE_3D && !vid.support.ext_texture_3d)
1709 Con_Printf ("R_LoadTexture: 3d texture not supported by driver\n");
1713 texinfo = R_GetTexTypeInfo(textype, flags);
1714 size = width * height * depth * sides * texinfo->inputbytesperpixel;
1717 Con_Printf ("R_LoadTexture: bogus texture size (%dx%dx%dx%dbppx%dsides = %d bytes)\n", width, height, depth, texinfo->inputbytesperpixel * 8, sides, size);
1721 // clear the alpha flag if the texture has no transparent pixels
1724 case TEXTYPE_PALETTE:
1725 case TEXTYPE_SRGB_PALETTE:
1726 if (flags & TEXF_ALPHA)
1728 flags &= ~TEXF_ALPHA;
1731 for (i = 0;i < size;i++)
1733 if (((unsigned char *)&palette[data[i]])[3] < 255)
1735 flags |= TEXF_ALPHA;
1744 case TEXTYPE_SRGB_RGBA:
1745 case TEXTYPE_SRGB_BGRA:
1746 if (flags & TEXF_ALPHA)
1748 flags &= ~TEXF_ALPHA;
1751 for (i = 3;i < size;i += 4)
1755 flags |= TEXF_ALPHA;
1762 case TEXTYPE_SHADOWMAP16_COMP:
1763 case TEXTYPE_SHADOWMAP16_RAW:
1764 case TEXTYPE_SHADOWMAP24_COMP:
1765 case TEXTYPE_SHADOWMAP24_RAW:
1768 case TEXTYPE_SRGB_DXT1:
1771 case TEXTYPE_SRGB_DXT1A:
1773 case TEXTYPE_SRGB_DXT3:
1775 case TEXTYPE_SRGB_DXT5:
1776 flags |= TEXF_ALPHA;
1779 flags |= TEXF_ALPHA;
1781 case TEXTYPE_COLORBUFFER:
1782 case TEXTYPE_COLORBUFFER16F:
1783 case TEXTYPE_COLORBUFFER32F:
1784 flags |= TEXF_ALPHA;
1787 Sys_Error("R_LoadTexture: unknown texture type");
1790 texinfo2 = R_GetTexTypeInfo(textype, flags);
1791 if(size == width * height * depth * sides * texinfo->inputbytesperpixel)
1794 Con_Printf ("R_LoadTexture: input size changed after alpha fallback\n");
1796 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
1798 strlcpy (glt->identifier, identifier, sizeof(glt->identifier));
1800 glt->chain = pool->gltchain;
1801 pool->gltchain = glt;
1802 glt->inputwidth = width;
1803 glt->inputheight = height;
1804 glt->inputdepth = depth;
1806 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
1807 glt->textype = texinfo;
1808 glt->texturetype = texturetype;
1809 glt->inputdatasize = size;
1810 glt->palette = palette;
1811 glt->glinternalformat = texinfo->glinternalformat;
1812 glt->glformat = texinfo->glformat;
1813 glt->gltype = texinfo->gltype;
1814 glt->bytesperpixel = texinfo->internalbytesperpixel;
1815 glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
1818 glt->glisdepthstencil = false;
1819 glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
1820 // init the dynamic texture attributes, too [11/22/2007 Black]
1821 glt->updatecallback = NULL;
1822 glt->updatecallback_data = NULL;
1824 GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth, &glt->miplevels);
1826 // upload the texture
1827 // data may be NULL (blank texture for dynamic rendering)
1828 switch(vid.renderpath)
1830 case RENDERPATH_GL11:
1831 case RENDERPATH_GL13:
1832 case RENDERPATH_GL20:
1833 case RENDERPATH_GLES1:
1834 case RENDERPATH_GLES2:
1836 qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
1838 case RENDERPATH_D3D9:
1841 D3DFORMAT d3dformat;
1846 d3dpool = D3DPOOL_MANAGED;
1847 if (flags & TEXF_RENDERTARGET)
1849 d3dusage |= D3DUSAGE_RENDERTARGET;
1850 d3dpool = D3DPOOL_DEFAULT;
1854 case TEXTYPE_PALETTE: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
1855 case TEXTYPE_RGBA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8B8G8R8 : D3DFMT_X8B8G8R8;break;
1856 case TEXTYPE_BGRA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
1857 case TEXTYPE_COLORBUFFER: d3dformat = D3DFMT_A8R8G8B8;break;
1858 case TEXTYPE_COLORBUFFER16F: d3dformat = D3DFMT_A16B16G16R16F;break;
1859 case TEXTYPE_COLORBUFFER32F: d3dformat = D3DFMT_A32B32G32R32F;break;
1860 case TEXTYPE_ALPHA: d3dformat = D3DFMT_A8;break;
1861 default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTexture: unsupported texture type %i when picking D3DFMT", (int)textype);break;
1863 glt->d3dformat = d3dformat;
1864 glt->d3dusage = d3dusage;
1865 glt->d3dpool = d3dpool;
1866 glt->d3disrendertargetsurface = false;
1867 glt->d3disdepthstencilsurface = false;
1868 if (glt->tiledepth > 1)
1870 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)))
1871 Sys_Error("IDirect3DDevice9_CreateVolumeTexture failed!");
1873 else if (glt->sides == 6)
1875 if (FAILED(d3dresult = IDirect3DDevice9_CreateCubeTexture(vid_d3d9dev, glt->tilewidth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DCubeTexture9 **)&glt->d3dtexture, NULL)))
1876 Sys_Error("IDirect3DDevice9_CreateCubeTexture failed!");
1880 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)))
1881 Sys_Error("IDirect3DDevice9_CreateTexture failed!");
1886 case RENDERPATH_D3D10:
1887 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1889 case RENDERPATH_D3D11:
1890 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1892 case RENDERPATH_SOFT:
1897 case TEXTYPE_PALETTE: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
1898 case TEXTYPE_RGBA: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA8;break;
1899 case TEXTYPE_BGRA: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
1900 case TEXTYPE_COLORBUFFER: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
1901 case TEXTYPE_COLORBUFFER16F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA16F;break;
1902 case TEXTYPE_COLORBUFFER32F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA32F;break;
1903 case TEXTYPE_SHADOWMAP16_COMP:
1904 case TEXTYPE_SHADOWMAP16_RAW:
1905 case TEXTYPE_SHADOWMAP24_COMP:
1906 case TEXTYPE_SHADOWMAP24_RAW: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
1907 case TEXTYPE_DEPTHBUFFER16:
1908 case TEXTYPE_DEPTHBUFFER24:
1909 case TEXTYPE_DEPTHBUFFER24STENCIL8: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
1910 case TEXTYPE_ALPHA: tflags = DPSOFTRAST_TEXTURE_FORMAT_ALPHA8;break;
1911 default: Sys_Error("R_LoadTexture: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
1913 if (glt->miplevels > 1) tflags |= DPSOFTRAST_TEXTURE_FLAG_MIPMAP;
1914 if (flags & TEXF_ALPHA) tflags |= DPSOFTRAST_TEXTURE_FLAG_USEALPHA;
1915 if (glt->sides == 6) tflags |= DPSOFTRAST_TEXTURE_FLAG_CUBEMAP;
1916 if (glt->flags & TEXF_CLAMP) tflags |= DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;
1917 glt->texnum = DPSOFTRAST_Texture_New(tflags, glt->tilewidth, glt->tileheight, glt->tiledepth);
1922 R_UploadFullTexture(glt, data);
1923 if ((glt->flags & TEXF_ALLOWUPDATES) && gl_nopartialtextureupdates.integer)
1924 glt->bufferpixels = (unsigned char *)Mem_Alloc(texturemempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
1926 // free any temporary processing buffer we allocated...
1928 Mem_Free(temppixels);
1930 // texture converting and uploading can take a while, so make sure we're sending keepalives
1931 // FIXME: this causes rendering during R_Shadow_DrawLights
1932 // CL_KeepaliveMessage(false);
1934 return (rtexture_t *)glt;
1937 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)
1939 return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, miplevel, textype, GLTEXTURETYPE_2D, data, palette);
1942 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)
1944 return R_SetupTexture(rtexturepool, identifier, width, height, depth, 1, flags, miplevel, textype, GLTEXTURETYPE_3D, data, palette);
1947 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)
1949 return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, miplevel, textype, GLTEXTURETYPE_CUBEMAP, data, palette);
1952 rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype, qboolean filter)
1954 return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_RENDERTARGET | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR : TEXF_FORCENEAREST), -1, textype, GLTEXTURETYPE_2D, NULL, NULL);
1957 rtexture_t *R_LoadTextureRenderBuffer(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype)
1960 gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
1961 textypeinfo_t *texinfo;
1963 if (cls.state == ca_dedicated)
1966 texinfo = R_GetTexTypeInfo(textype, TEXF_RENDERTARGET | TEXF_CLAMP);
1968 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
1970 strlcpy (glt->identifier, identifier, sizeof(glt->identifier));
1972 glt->chain = pool->gltchain;
1973 pool->gltchain = glt;
1974 glt->inputwidth = width;
1975 glt->inputheight = height;
1976 glt->inputdepth = 1;
1977 glt->flags = TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_FORCENEAREST;
1979 glt->textype = texinfo;
1980 glt->texturetype = textype;
1981 glt->inputdatasize = width*height*texinfo->internalbytesperpixel;
1982 glt->palette = NULL;
1983 glt->glinternalformat = texinfo->glinternalformat;
1984 glt->glformat = texinfo->glformat;
1985 glt->gltype = texinfo->gltype;
1986 glt->bytesperpixel = texinfo->internalbytesperpixel;
1987 glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
1990 glt->glisdepthstencil = textype == TEXTYPE_DEPTHBUFFER24STENCIL8;
1991 glt->gltexturetypeenum = GL_TEXTURE_2D;
1992 // init the dynamic texture attributes, too [11/22/2007 Black]
1993 glt->updatecallback = NULL;
1994 glt->updatecallback_data = NULL;
1996 GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth, &glt->miplevels);
1998 // upload the texture
1999 // data may be NULL (blank texture for dynamic rendering)
2000 switch(vid.renderpath)
2002 case RENDERPATH_GL11:
2003 case RENDERPATH_GL13:
2004 case RENDERPATH_GL20:
2005 case RENDERPATH_GLES1:
2006 case RENDERPATH_GLES2:
2008 qglGenRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR
2009 qglBindRenderbuffer(GL_RENDERBUFFER, glt->renderbuffernum);CHECKGLERROR
2010 qglRenderbufferStorage(GL_RENDERBUFFER, glt->glinternalformat, glt->tilewidth, glt->tileheight);CHECKGLERROR
2011 // 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
2012 qglBindRenderbuffer(GL_RENDERBUFFER, 0);CHECKGLERROR
2014 case RENDERPATH_D3D9:
2017 D3DFORMAT d3dformat;
2019 glt->d3disrendertargetsurface = false;
2020 glt->d3disdepthstencilsurface = false;
2023 case TEXTYPE_COLORBUFFER: d3dformat = D3DFMT_A8R8G8B8;glt->d3disrendertargetsurface = true;break;
2024 case TEXTYPE_COLORBUFFER16F: d3dformat = D3DFMT_A16B16G16R16F;glt->d3disrendertargetsurface = true;break;
2025 case TEXTYPE_COLORBUFFER32F: d3dformat = D3DFMT_A32B32G32R32F;glt->d3disrendertargetsurface = true;break;
2026 case TEXTYPE_DEPTHBUFFER16: d3dformat = D3DFMT_D16;glt->d3disdepthstencilsurface = true;break;
2027 case TEXTYPE_DEPTHBUFFER24: d3dformat = D3DFMT_D24X8;glt->d3disdepthstencilsurface = true;break;
2028 case TEXTYPE_DEPTHBUFFER24STENCIL8: d3dformat = D3DFMT_D24S8;glt->d3disdepthstencilsurface = true;break;
2029 default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTextureRenderbuffer: unsupported texture type %i when picking D3DFMT", (int)textype);break;
2031 glt->d3dformat = d3dformat;
2034 if (glt->d3disrendertargetsurface)
2036 if (FAILED(d3dresult = IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
2037 Sys_Error("IDirect3DDevice9_CreateRenderTarget failed!");
2039 else if (glt->d3disdepthstencilsurface)
2041 if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
2042 Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
2047 case RENDERPATH_D3D10:
2048 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2050 case RENDERPATH_D3D11:
2051 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2053 case RENDERPATH_SOFT:
2058 case TEXTYPE_COLORBUFFER: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8 | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2059 case TEXTYPE_COLORBUFFER16F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA16F | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2060 case TEXTYPE_COLORBUFFER32F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA32F | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2061 case TEXTYPE_DEPTHBUFFER16:
2062 case TEXTYPE_DEPTHBUFFER24:
2063 case TEXTYPE_DEPTHBUFFER24STENCIL8: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2064 default: Sys_Error("R_LoadTextureRenderbuffer: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
2066 glt->texnum = DPSOFTRAST_Texture_New(tflags, glt->tilewidth, glt->tileheight, glt->tiledepth);
2071 return (rtexture_t *)glt;
2074 int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha)
2077 return -1; // unsupported on this platform
2079 gltexture_t *glt = (gltexture_t *)rt;
2082 int bytesperpixel = 0;
2083 int bytesperblock = 0;
2085 int dds_format_flags;
2093 GLint internalformat;
2094 const char *ddsfourcc;
2096 return -1; // NULL pointer
2097 if (!strcmp(gl_version, "2.0.5885 WinXP Release"))
2098 return -2; // broken driver - crashes on reading internal format
2099 if (!qglGetTexLevelParameteriv)
2101 GL_ActiveTexture(0);
2102 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
2103 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
2104 qglGetTexLevelParameteriv(gltexturetypeenums[glt->texturetype], 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat);
2105 switch(internalformat)
2107 default: ddsfourcc = NULL;bytesperpixel = 4;break;
2108 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
2109 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: ddsfourcc = "DXT1";bytesperblock = 8;break;
2110 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: ddsfourcc = "DXT3";bytesperblock = 16;break;
2111 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: ddsfourcc = "DXT5";bytesperblock = 16;break;
2113 // if premultiplied alpha, say so in the DDS file
2114 if(glt->flags & TEXF_RGBMULTIPLYBYALPHA)
2116 switch(internalformat)
2118 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: ddsfourcc = "DXT2";break;
2119 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: ddsfourcc = "DXT4";break;
2122 if (!bytesperblock && skipuncompressed)
2123 return -3; // skipped
2124 memset(mipinfo, 0, sizeof(mipinfo));
2125 mipinfo[0][0] = glt->tilewidth;
2126 mipinfo[0][1] = glt->tileheight;
2128 if ((glt->flags & TEXF_MIPMAP) && !(glt->tilewidth == 1 && glt->tileheight == 1))
2130 for (mip = 1;mip < 16;mip++)
2132 mipinfo[mip][0] = mipinfo[mip-1][0] > 1 ? mipinfo[mip-1][0] >> 1 : 1;
2133 mipinfo[mip][1] = mipinfo[mip-1][1] > 1 ? mipinfo[mip-1][1] >> 1 : 1;
2134 if (mipinfo[mip][0] == 1 && mipinfo[mip][1] == 1)
2142 for (mip = 0;mip < mipmaps;mip++)
2144 mipinfo[mip][2] = bytesperblock ? ((mipinfo[mip][0]+3)/4)*((mipinfo[mip][1]+3)/4)*bytesperblock : mipinfo[mip][0]*mipinfo[mip][1]*bytesperpixel;
2145 mipinfo[mip][3] = ddssize;
2146 ddssize += mipinfo[mip][2];
2148 dds = (unsigned char *)Mem_Alloc(tempmempool, ddssize);
2151 dds_caps1 = 0x1000; // DDSCAPS_TEXTURE
2155 dds_flags = 0x81007; // DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_LINEARSIZE
2156 dds_format_flags = 0x4; // DDPF_FOURCC
2160 dds_flags = 0x100F; // DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH
2161 dds_format_flags = 0x40; // DDPF_RGB
2165 dds_flags |= 0x20000; // DDSD_MIPMAPCOUNT
2166 dds_caps1 |= 0x400008; // DDSCAPS_MIPMAP | DDSCAPS_COMPLEX
2169 dds_format_flags |= 0x1; // DDPF_ALPHAPIXELS
2170 memcpy(dds, "DDS ", 4);
2171 StoreLittleLong(dds+4, 124); // http://msdn.microsoft.com/en-us/library/bb943982%28v=vs.85%29.aspx says so
2172 StoreLittleLong(dds+8, dds_flags);
2173 StoreLittleLong(dds+12, mipinfo[0][1]); // height
2174 StoreLittleLong(dds+16, mipinfo[0][0]); // width
2175 StoreLittleLong(dds+24, 0); // depth
2176 StoreLittleLong(dds+28, mipmaps); // mipmaps
2177 StoreLittleLong(dds+76, 32); // format size
2178 StoreLittleLong(dds+80, dds_format_flags);
2179 StoreLittleLong(dds+108, dds_caps1);
2180 StoreLittleLong(dds+112, dds_caps2);
2183 StoreLittleLong(dds+20, mipinfo[0][2]); // linear size
2184 memcpy(dds+84, ddsfourcc, 4);
2185 for (mip = 0;mip < mipmaps;mip++)
2187 qglGetCompressedTexImageARB(gltexturetypeenums[glt->texturetype], mip, dds + mipinfo[mip][3]);CHECKGLERROR
2192 StoreLittleLong(dds+20, mipinfo[0][0]*bytesperpixel); // pitch
2193 StoreLittleLong(dds+88, bytesperpixel*8); // bits per pixel
2194 dds[94] = dds[97] = dds[100] = dds[107] = 255; // bgra byte order masks
2195 for (mip = 0;mip < mipmaps;mip++)
2197 qglGetTexImage(gltexturetypeenums[glt->texturetype], mip, GL_BGRA, GL_UNSIGNED_BYTE, dds + mipinfo[mip][3]);CHECKGLERROR
2200 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2201 ret = FS_WriteFile(filename, dds, ddssize);
2203 return ret ? ddssize : -5;
2208 // ELUAN: FIXME: separate this code
2209 #include "ktx10/include/ktx.h"
2212 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
2214 int i, size, dds_format_flags, dds_miplevels, dds_width, dds_height;
2217 int bytesperblock, bytesperpixel;
2220 gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
2221 textypeinfo_t *texinfo;
2222 int mip, mipwidth, mipheight, mipsize, mipsize_total;
2223 unsigned int c, r, g, b;
2224 GLint oldbindtexnum = 0;
2225 unsigned char *mippixels;
2226 unsigned char *mippixels_start;
2227 unsigned char *ddspixels;
2229 fs_offset_t ddsfilesize;
2230 unsigned int ddssize;
2231 qboolean force_swdecode, npothack;
2233 // ELUAN: FIXME: separate this code
2237 KTX_dimensions sizes;
2240 if (cls.state == ca_dedicated)
2244 // ELUAN: FIXME: separate this code
2245 if (vid.renderpath != RENDERPATH_GLES2)
2247 Con_DPrintf("KTX texture format is only supported on the GLES2 renderpath\n");
2251 // some textures are specified with extensions, so it becomes .tga.dds
2252 FS_StripExtension (filename, vabuf2, sizeof(vabuf2));
2253 FS_StripExtension (vabuf2, vabuf, sizeof(vabuf));
2254 FS_DefaultExtension (vabuf, ".ktx", sizeof(vabuf));
2255 strsize = strlen(vabuf);
2257 for (i = 0; i <= strsize - 4; i++) // copy null termination
2258 vabuf[i] = vabuf[i + 4];
2260 Con_DPrintf("Loading %s...\n", vabuf);
2261 dds = FS_LoadFile(vabuf, tempmempool, true, &ddsfilesize);
2262 ddssize = ddsfilesize;
2266 Con_DPrintf("Not found!\n");
2267 return NULL; // not found
2269 Con_DPrintf("Found!\n");
2271 if (flags & TEXF_ALPHA)
2273 Con_DPrintf("KTX texture with alpha not supported yet, disabling\n");
2274 flags &= ~TEXF_ALPHA;
2280 GLboolean isMipmapped;
2281 KTX_error_code ktxerror;
2283 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
2285 // texture uploading can take a while, so make sure we're sending keepalives
2286 CL_KeepaliveMessage(false);
2288 // create the texture object
2290 GL_ActiveTexture(0);
2291 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[GLTEXTURETYPE_2D]);
2292 qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
2293 qglBindTexture(gltexturetypeenums[GLTEXTURETYPE_2D], glt->texnum);CHECKGLERROR
2295 // upload the texture
2296 // we need to restore the texture binding after finishing the upload
2298 // NOTE: some drivers fail with ETC1 NPOT (only PowerVR?). This may make the driver crash later.
2299 ktxerror = ktxLoadTextureM(dds, ddssize, &glt->texnum, &target, &sizes, &isMipmapped, &glerror,
2300 0, NULL);// can't CHECKGLERROR, the lib catches it
2302 // FIXME: delete texture if we fail here
2303 if (target != GL_TEXTURE_2D)
2305 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2307 Con_DPrintf("%s target != GL_TEXTURE_2D, target == %x\n", vabuf, target);
2308 return NULL; // FIXME: delete the texture from memory
2311 if (KTX_SUCCESS == ktxerror)
2313 textype = TEXTYPE_ETC1;
2314 flags &= ~TEXF_COMPRESS; // don't let the textype be wrong
2316 // return whether this texture is transparent
2318 *hasalphaflag = (flags & TEXF_ALPHA) != 0;
2320 // TODO: apply gl_picmip
2323 // TODO: only load mipmaps if requested
2326 flags |= TEXF_MIPMAP;
2328 flags &= ~TEXF_MIPMAP;
2330 texinfo = R_GetTexTypeInfo(textype, flags);
2332 strlcpy (glt->identifier, vabuf, sizeof(glt->identifier));
2334 glt->chain = pool->gltchain;
2335 pool->gltchain = glt;
2336 glt->inputwidth = sizes.width;
2337 glt->inputheight = sizes.height;
2338 glt->inputdepth = 1;
2340 glt->textype = texinfo;
2341 glt->texturetype = GLTEXTURETYPE_2D;
2342 glt->inputdatasize = ddssize;
2343 glt->glinternalformat = texinfo->glinternalformat;
2344 glt->glformat = texinfo->glformat;
2345 glt->gltype = texinfo->gltype;
2346 glt->bytesperpixel = texinfo->internalbytesperpixel;
2348 glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
2349 glt->tilewidth = sizes.width;
2350 glt->tileheight = sizes.height;
2352 glt->miplevels = isMipmapped ? 1 : 0; // FIXME
2354 // after upload we have to set some parameters...
2355 #ifdef GL_TEXTURE_MAX_LEVEL
2357 if (dds_miplevels >= 1 && !mipcomplete)
2359 // need to set GL_TEXTURE_MAX_LEVEL
2360 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR
2364 GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
2366 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2368 return (rtexture_t *)glt;
2372 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2374 Con_DPrintf("KTX texture %s failed to load: %x\n", vabuf, ktxerror);
2378 #endif // __ANDROID__
2380 dds = FS_LoadFile(filename, tempmempool, true, &ddsfilesize);
2381 ddssize = ddsfilesize;
2385 if (r_texture_dds_load_logfailure.integer && (r_texture_dds_load_logfailure.integer >= 2 || !optionaltexture))
2386 Log_Printf("ddstexturefailures.log", "%s\n", filename);
2387 return NULL; // not found
2390 if (ddsfilesize <= 128 || memcmp(dds, "DDS ", 4) || ddssize < (unsigned int)BuffLittleLong(dds+4) || BuffLittleLong(dds+76) != 32)
2393 Con_Printf("^1%s: not a DDS image\n", filename);
2397 //dds_flags = BuffLittleLong(dds+8);
2398 dds_format_flags = BuffLittleLong(dds+80);
2399 dds_miplevels = (BuffLittleLong(dds+108) & 0x400000) ? BuffLittleLong(dds+28) : 1;
2400 dds_width = BuffLittleLong(dds+16);
2401 dds_height = BuffLittleLong(dds+12);
2402 ddspixels = dds + 128;
2404 if(r_texture_dds_load_alphamode.integer == 0)
2405 if(!(dds_format_flags & 0x1)) // DDPF_ALPHAPIXELS
2406 flags &= ~TEXF_ALPHA;
2408 //flags &= ~TEXF_ALPHA; // disabled, as we DISABLE TEXF_ALPHA in the alpha detection, not enable it!
2409 if ((dds_format_flags & 0x40) && BuffLittleLong(dds+88) == 32)
2411 // very sloppy BGRA 32bit identification
2412 textype = TEXTYPE_BGRA;
2413 flags &= ~TEXF_COMPRESS; // don't let the textype be wrong
2416 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(dds_width, dds_height), bytesperpixel);
2417 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2420 Con_Printf("^1%s: invalid BGRA DDS image\n", filename);
2423 if((r_texture_dds_load_alphamode.integer == 1) && (flags & TEXF_ALPHA))
2426 for (i = 3;i < size;i += 4)
2427 if (ddspixels[i] < 255)
2430 flags &= ~TEXF_ALPHA;
2433 else if (!memcmp(dds+84, "DXT1", 4))
2435 // we need to find out if this is DXT1 (opaque) or DXT1A (transparent)
2436 // LordHavoc: it is my belief that this does not infringe on the
2437 // patent because it is not decoding pixels...
2438 textype = TEXTYPE_DXT1;
2441 //size = ((dds_width+3)/4)*((dds_height+3)/4)*bytesperblock;
2442 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2443 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2446 Con_Printf("^1%s: invalid DXT1 DDS image\n", filename);
2449 if (flags & TEXF_ALPHA)
2451 if (r_texture_dds_load_alphamode.integer == 1)
2454 for (i = 0;i < size;i += bytesperblock)
2455 if (ddspixels[i+0] + ddspixels[i+1] * 256 <= ddspixels[i+2] + ddspixels[i+3] * 256)
2457 // NOTE: this assumes sizeof(unsigned int) == 4
2458 unsigned int data = * (unsigned int *) &(ddspixels[i+4]);
2459 // check if data, in base 4, contains a digit 3 (DXT1: transparent pixel)
2460 if(data & (data<<1) & 0xAAAAAAAA)//rgh
2464 textype = TEXTYPE_DXT1A;
2466 flags &= ~TEXF_ALPHA;
2468 else if (r_texture_dds_load_alphamode.integer == 0)
2469 textype = TEXTYPE_DXT1A;
2472 flags &= ~TEXF_ALPHA;
2476 else if (!memcmp(dds+84, "DXT3", 4) || !memcmp(dds+84, "DXT2", 4))
2478 if(!memcmp(dds+84, "DXT2", 4))
2480 if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
2482 Con_Printf("^1%s: expecting DXT3 image without premultiplied alpha, got DXT2 image with premultiplied alpha\n", filename);
2487 if(flags & TEXF_RGBMULTIPLYBYALPHA)
2489 Con_Printf("^1%s: expecting DXT2 image without premultiplied alpha, got DXT3 image without premultiplied alpha\n", filename);
2492 textype = TEXTYPE_DXT3;
2495 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2496 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2499 Con_Printf("^1%s: invalid DXT3 DDS image\n", filename);
2502 // we currently always assume alpha
2504 else if (!memcmp(dds+84, "DXT5", 4) || !memcmp(dds+84, "DXT4", 4))
2506 if(!memcmp(dds+84, "DXT4", 4))
2508 if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
2510 Con_Printf("^1%s: expecting DXT5 image without premultiplied alpha, got DXT4 image with premultiplied alpha\n", filename);
2515 if(flags & TEXF_RGBMULTIPLYBYALPHA)
2517 Con_Printf("^1%s: expecting DXT4 image without premultiplied alpha, got DXT5 image without premultiplied alpha\n", filename);
2520 textype = TEXTYPE_DXT5;
2523 size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2524 if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2527 Con_Printf("^1%s: invalid DXT5 DDS image\n", filename);
2530 // we currently always assume alpha
2535 Con_Printf("^1%s: unrecognized/unsupported DDS format\n", filename);
2539 // when requesting a non-alpha texture and we have DXT3/5, convert to DXT1
2540 if(!(flags & TEXF_ALPHA) && (textype == TEXTYPE_DXT3 || textype == TEXTYPE_DXT5))
2542 textype = TEXTYPE_DXT1;
2546 for (i = 0;i < (int)ddssize;i += bytesperblock)
2547 memcpy(&ddspixels[i], &ddspixels[(i<<1)+8], 8);
2551 force_swdecode = false;
2553 (!vid.support.arb_texture_non_power_of_two &&
2555 (dds_width & (dds_width - 1))
2557 (dds_height & (dds_height - 1))
2562 if(vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && !npothack)
2564 if(r_texture_dds_swdecode.integer > 1)
2565 force_swdecode = true;
2569 if(r_texture_dds_swdecode.integer < 1)
2575 force_swdecode = true;
2579 // return whether this texture is transparent
2581 *hasalphaflag = (flags & TEXF_ALPHA) != 0;
2583 // if we SW decode, choose 2 sizes bigger
2586 // this is quarter res, so do not scale down more than we have to
2590 Con_DPrintf("WARNING: fake software decoding of compressed texture %s degraded quality\n", filename);
2593 // this is where we apply gl_picmip
2594 mippixels_start = ddspixels;
2595 mipwidth = dds_width;
2596 mipheight = dds_height;
2597 while(miplevel >= 1 && dds_miplevels >= 1)
2599 if (mipwidth <= 1 && mipheight <= 1)
2601 mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2602 mippixels_start += mipsize; // just skip
2610 mipsize_total = ddssize - 128 - (mippixels_start - ddspixels);
2611 mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2613 // from here on, we do not need the ddspixels and ddssize any more (apart from the statistics entry in glt)
2615 // fake decode S3TC if needed
2618 int mipsize_new = mipsize_total / bytesperblock * 4;
2619 unsigned char *mipnewpixels = (unsigned char *) Mem_Alloc(tempmempool, mipsize_new);
2620 unsigned char *p = mipnewpixels;
2621 for (i = bytesperblock == 16 ? 8 : 0;i < (int)mipsize_total;i += bytesperblock, p += 4)
2623 c = mippixels_start[i] + 256*mippixels_start[i+1] + 65536*mippixels_start[i+2] + 16777216*mippixels_start[i+3];
2624 p[2] = (((c >> 11) & 0x1F) + ((c >> 27) & 0x1F)) * (0.5f / 31.0f * 255.0f);
2625 p[1] = (((c >> 5) & 0x3F) + ((c >> 21) & 0x3F)) * (0.5f / 63.0f * 255.0f);
2626 p[0] = (((c ) & 0x1F) + ((c >> 16) & 0x1F)) * (0.5f / 31.0f * 255.0f);
2627 if(textype == TEXTYPE_DXT5)
2628 p[3] = (0.5 * mippixels_start[i-8] + 0.5 * mippixels_start[i-7]);
2629 else if(textype == TEXTYPE_DXT3)
2631 (mippixels_start[i-8] & 0x0F)
2632 + (mippixels_start[i-8] >> 4)
2633 + (mippixels_start[i-7] & 0x0F)
2634 + (mippixels_start[i-7] >> 4)
2635 + (mippixels_start[i-6] & 0x0F)
2636 + (mippixels_start[i-6] >> 4)
2637 + (mippixels_start[i-5] & 0x0F)
2638 + (mippixels_start[i-5] >> 4)
2639 ) * (0.125f / 15.0f * 255.0f);
2644 textype = TEXTYPE_BGRA;
2648 // as each block becomes a pixel, we must use pixel count for this
2649 mipwidth = (mipwidth + 3) / 4;
2650 mipheight = (mipheight + 3) / 4;
2651 mipsize = bytesperpixel * mipwidth * mipheight;
2652 mippixels_start = mipnewpixels;
2653 mipsize_total = mipsize_new;
2656 // start mip counting
2657 mippixels = mippixels_start;
2659 // calculate average color if requested
2663 Vector4Clear(avgcolor);
2666 for (i = bytesperblock == 16 ? 8 : 0;i < mipsize;i += bytesperblock)
2668 c = mippixels[i] + 256*mippixels[i+1] + 65536*mippixels[i+2] + 16777216*mippixels[i+3];
2669 avgcolor[0] += ((c >> 11) & 0x1F) + ((c >> 27) & 0x1F);
2670 avgcolor[1] += ((c >> 5) & 0x3F) + ((c >> 21) & 0x3F);
2671 avgcolor[2] += ((c ) & 0x1F) + ((c >> 16) & 0x1F);
2672 if(textype == TEXTYPE_DXT5)
2673 avgcolor[3] += (mippixels[i-8] + (int) mippixels[i-7]) * (0.5f / 255.0f);
2674 else if(textype == TEXTYPE_DXT3)
2676 (mippixels_start[i-8] & 0x0F)
2677 + (mippixels_start[i-8] >> 4)
2678 + (mippixels_start[i-7] & 0x0F)
2679 + (mippixels_start[i-7] >> 4)
2680 + (mippixels_start[i-6] & 0x0F)
2681 + (mippixels_start[i-6] >> 4)
2682 + (mippixels_start[i-5] & 0x0F)
2683 + (mippixels_start[i-5] >> 4)
2684 ) * (0.125f / 15.0f);
2686 avgcolor[3] += 1.0f;
2688 f = (float)bytesperblock / mipsize;
2689 avgcolor[0] *= (0.5f / 31.0f) * f;
2690 avgcolor[1] *= (0.5f / 63.0f) * f;
2691 avgcolor[2] *= (0.5f / 31.0f) * f;
2696 for (i = 0;i < mipsize;i += 4)
2698 avgcolor[0] += mippixels[i+2];
2699 avgcolor[1] += mippixels[i+1];
2700 avgcolor[2] += mippixels[i];
2701 avgcolor[3] += mippixels[i+3];
2703 f = (1.0f / 255.0f) * bytesperpixel / mipsize;
2711 // if we want sRGB, convert now
2714 if (vid.support.ext_texture_srgb)
2718 case TEXTYPE_DXT1: textype = TEXTYPE_SRGB_DXT1 ;break;
2719 case TEXTYPE_DXT1A: textype = TEXTYPE_SRGB_DXT1A ;break;
2720 case TEXTYPE_DXT3: textype = TEXTYPE_SRGB_DXT3 ;break;
2721 case TEXTYPE_DXT5: textype = TEXTYPE_SRGB_DXT5 ;break;
2722 case TEXTYPE_RGBA: textype = TEXTYPE_SRGB_RGBA ;break;
2736 for (i = bytesperblock == 16 ? 8 : 0;i < mipsize_total;i += bytesperblock)
2738 int c0, c1, c0new, c1new;
2739 c0 = mippixels_start[i] + 256*mippixels_start[i+1];
2740 r = ((c0 >> 11) & 0x1F);
2741 g = ((c0 >> 5) & 0x3F);
2743 r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2744 g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2745 b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2746 c0new = (r << 11) | (g << 5) | b;
2747 c1 = mippixels_start[i+2] + 256*mippixels_start[i+3];
2748 r = ((c1 >> 11) & 0x1F);
2749 g = ((c1 >> 5) & 0x3F);
2751 r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2752 g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2753 b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2754 c1new = (r << 11) | (g << 5) | b;
2755 // swap the colors if needed to fix order
2756 if(c0 > c1) // thirds
2764 mippixels_start[i+4] ^= 0x55;
2765 mippixels_start[i+5] ^= 0x55;
2766 mippixels_start[i+6] ^= 0x55;
2767 mippixels_start[i+7] ^= 0x55;
2769 else if(c0new == c1new)
2771 mippixels_start[i+4] = 0x00;
2772 mippixels_start[i+5] = 0x00;
2773 mippixels_start[i+6] = 0x00;
2774 mippixels_start[i+7] = 0x00;
2777 else // half + transparent
2784 mippixels_start[i+4] ^= (~mippixels_start[i+4] >> 1) & 0x55;
2785 mippixels_start[i+5] ^= (~mippixels_start[i+5] >> 1) & 0x55;
2786 mippixels_start[i+6] ^= (~mippixels_start[i+6] >> 1) & 0x55;
2787 mippixels_start[i+7] ^= (~mippixels_start[i+7] >> 1) & 0x55;
2790 mippixels_start[i] = c0new & 255;
2791 mippixels_start[i+1] = c0new >> 8;
2792 mippixels_start[i+2] = c1new & 255;
2793 mippixels_start[i+3] = c1new >> 8;
2798 Image_MakeLinearColorsFromsRGB(mippixels, mippixels, mipsize_total / bytesperblock);
2806 // when not requesting mipmaps, do not load them
2807 if(!(flags & TEXF_MIPMAP))
2810 if (dds_miplevels >= 1)
2811 flags |= TEXF_MIPMAP;
2813 flags &= ~TEXF_MIPMAP;
2815 texinfo = R_GetTexTypeInfo(textype, flags);
2817 glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
2818 strlcpy (glt->identifier, filename, sizeof(glt->identifier));
2820 glt->chain = pool->gltchain;
2821 pool->gltchain = glt;
2822 glt->inputwidth = mipwidth;
2823 glt->inputheight = mipheight;
2824 glt->inputdepth = 1;
2826 glt->textype = texinfo;
2827 glt->texturetype = GLTEXTURETYPE_2D;
2828 glt->inputdatasize = ddssize;
2829 glt->glinternalformat = texinfo->glinternalformat;
2830 glt->glformat = texinfo->glformat;
2831 glt->gltype = texinfo->gltype;
2832 glt->bytesperpixel = texinfo->internalbytesperpixel;
2834 glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
2835 glt->tilewidth = mipwidth;
2836 glt->tileheight = mipheight;
2838 glt->miplevels = dds_miplevels;
2842 for (glt->tilewidth = 1;glt->tilewidth < mipwidth;glt->tilewidth <<= 1);
2843 for (glt->tileheight = 1;glt->tileheight < mipheight;glt->tileheight <<= 1);
2846 // texture uploading can take a while, so make sure we're sending keepalives
2847 CL_KeepaliveMessage(false);
2849 // create the texture object
2850 switch(vid.renderpath)
2852 case RENDERPATH_GL11:
2853 case RENDERPATH_GL13:
2854 case RENDERPATH_GL20:
2855 case RENDERPATH_GLES1:
2856 case RENDERPATH_GLES2:
2858 GL_ActiveTexture(0);
2859 oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
2860 qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
2861 qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
2863 case RENDERPATH_D3D9:
2866 D3DFORMAT d3dformat;
2871 case TEXTYPE_BGRA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
2872 case TEXTYPE_DXT1: case TEXTYPE_DXT1A: d3dformat = D3DFMT_DXT1;break;
2873 case TEXTYPE_DXT3: d3dformat = D3DFMT_DXT3;break;
2874 case TEXTYPE_DXT5: d3dformat = D3DFMT_DXT5;break;
2875 default: d3dformat = D3DFMT_A8R8G8B8;Host_Error("R_LoadTextureDDSFile: unsupported texture type %i when picking D3DFMT", (int)textype);break;
2878 d3dpool = D3DPOOL_MANAGED;
2879 IDirect3DDevice9_CreateTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->miplevels, d3dusage, d3dformat, d3dpool, (IDirect3DTexture9 **)&glt->d3dtexture, NULL);
2883 case RENDERPATH_D3D10:
2884 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2886 case RENDERPATH_D3D11:
2887 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2889 case RENDERPATH_SOFT:
2890 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);
2894 // upload the texture
2895 // we need to restore the texture binding after finishing the upload
2896 mipcomplete = false;
2898 for (mip = 0;mip <= dds_miplevels;mip++) // <= to include the not-counted "largest" miplevel
2900 unsigned char *upload_mippixels = mippixels;
2901 int upload_mipwidth = mipwidth;
2902 int upload_mipheight = mipheight;
2903 mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2904 if (mippixels + mipsize > mippixels_start + mipsize_total)
2908 upload_mipwidth = (glt->tilewidth >> mip);
2909 upload_mipheight = (glt->tileheight >> mip);
2910 if(upload_mipwidth != mipwidth || upload_mipheight != mipheight)
2911 // I _think_ they always mismatch, but I was too lazy
2912 // to properly check, and this test here is really
2915 upload_mippixels = (unsigned char *) Mem_Alloc(tempmempool, 4 * upload_mipwidth * upload_mipheight);
2916 Image_Resample32(mippixels, mipwidth, mipheight, 1, upload_mippixels, upload_mipwidth, upload_mipheight, 1, r_lerpimages.integer);
2919 switch(vid.renderpath)
2921 case RENDERPATH_GL11:
2922 case RENDERPATH_GL13:
2923 case RENDERPATH_GL20:
2924 case RENDERPATH_GLES1:
2925 case RENDERPATH_GLES2:
2928 qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, mipsize, upload_mippixels);CHECKGLERROR
2932 qglTexImage2D(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, glt->glformat, glt->gltype, upload_mippixels);CHECKGLERROR
2935 case RENDERPATH_D3D9:
2938 D3DLOCKED_RECT d3dlockedrect;
2939 if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
2941 memcpy(d3dlockedrect.pBits, upload_mippixels, mipsize);
2942 IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
2948 case RENDERPATH_D3D10:
2949 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2951 case RENDERPATH_D3D11:
2952 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2954 case RENDERPATH_SOFT:
2956 Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2958 DPSOFTRAST_Texture_UpdateFull(glt->texnum, upload_mippixels);
2959 // DPSOFTRAST calculates its own mipmaps
2960 mip = dds_miplevels;
2963 if(upload_mippixels != mippixels)
2964 Mem_Free(upload_mippixels);
2965 mippixels += mipsize;
2966 if (mipwidth <= 1 && mipheight <= 1)
2977 // after upload we have to set some parameters...
2978 switch(vid.renderpath)
2980 case RENDERPATH_GL11:
2981 case RENDERPATH_GL13:
2982 case RENDERPATH_GL20:
2983 case RENDERPATH_GLES1:
2984 case RENDERPATH_GLES2:
2985 #ifdef GL_TEXTURE_MAX_LEVEL
2986 if (dds_miplevels >= 1 && !mipcomplete)
2988 // need to set GL_TEXTURE_MAX_LEVEL
2989 qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR
2992 GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
2993 qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2995 case RENDERPATH_D3D9:
2997 glt->d3daddressw = 0;
2998 if (glt->flags & TEXF_CLAMP)
3000 glt->d3daddressu = D3DTADDRESS_CLAMP;
3001 glt->d3daddressv = D3DTADDRESS_CLAMP;
3002 if (glt->tiledepth > 1)
3003 glt->d3daddressw = D3DTADDRESS_CLAMP;
3007 glt->d3daddressu = D3DTADDRESS_WRAP;
3008 glt->d3daddressv = D3DTADDRESS_WRAP;
3009 if (glt->tiledepth > 1)
3010 glt->d3daddressw = D3DTADDRESS_WRAP;
3012 glt->d3dmipmaplodbias = 0;
3013 glt->d3dmaxmiplevel = 0;
3014 glt->d3dmaxmiplevelfilter = 0;
3015 if (glt->flags & TEXF_MIPMAP)
3017 glt->d3dminfilter = d3d_filter_mipmin;
3018 glt->d3dmagfilter = d3d_filter_mipmag;
3019 glt->d3dmipfilter = d3d_filter_mipmix;
3023 glt->d3dminfilter = d3d_filter_flatmin;
3024 glt->d3dmagfilter = d3d_filter_flatmag;
3025 glt->d3dmipfilter = d3d_filter_flatmix;
3029 case RENDERPATH_D3D10:
3030 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3032 case RENDERPATH_D3D11:
3033 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3035 case RENDERPATH_SOFT:
3036 if (glt->flags & TEXF_FORCELINEAR)
3037 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
3038 else if (glt->flags & TEXF_FORCENEAREST)
3039 DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
3040 else if (glt->flags & TEXF_MIPMAP)
3041 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
3043 DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
3049 Mem_Free((unsigned char *) mippixels_start);
3050 return (rtexture_t *)glt;
3053 int R_TextureWidth(rtexture_t *rt)
3055 return rt ? ((gltexture_t *)rt)->inputwidth : 0;
3058 int R_TextureHeight(rtexture_t *rt)
3060 return rt ? ((gltexture_t *)rt)->inputheight : 0;
3063 int R_TextureFlags(rtexture_t *rt)
3065 return rt ? ((gltexture_t *)rt)->flags : 0;
3068 void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int z, int width, int height, int depth)
3070 gltexture_t *glt = (gltexture_t *)rt;
3072 Host_Error("R_UpdateTexture: no data supplied");
3074 Host_Error("R_UpdateTexture: no texture supplied");
3075 if (!glt->texnum && !glt->d3dtexture)
3077 Con_DPrintf("R_UpdateTexture: texture %p \"%s\" in pool %p has not been uploaded yet\n", (void *)glt, glt->identifier, (void *)glt->pool);
3080 // update part of the texture
3081 if (glt->bufferpixels)
3084 int bpp = glt->bytesperpixel;
3085 int inputskip = width*bpp;
3086 int outputskip = glt->tilewidth*bpp;
3087 const unsigned char *input = data;
3088 unsigned char *output = glt->bufferpixels;
3089 if (glt->inputdepth != 1 || glt->sides != 1)
3090 Sys_Error("R_UpdateTexture on buffered texture that is not 2D\n");
3100 input -= y*inputskip;
3103 if (width > glt->tilewidth - x)
3104 width = glt->tilewidth - x;
3105 if (height > glt->tileheight - y)
3106 height = glt->tileheight - y;
3107 if (width < 1 || height < 1)
3110 glt->buffermodified = true;
3111 output += y*outputskip + x*bpp;
3112 for (j = 0;j < height;j++, output += outputskip, input += inputskip)
3113 memcpy(output, input, width*bpp);
3115 else if (x || y || z || width != glt->inputwidth || height != glt->inputheight || depth != glt->inputdepth)
3116 R_UploadPartialTexture(glt, data, x, y, z, width, height, depth);
3118 R_UploadFullTexture(glt, data);
3121 int R_RealGetTexture(rtexture_t *rt)
3126 glt = (gltexture_t *)rt;
3127 if (glt->flags & GLTEXF_DYNAMIC)
3128 R_UpdateDynamicTexture(glt);
3129 if (glt->buffermodified && glt->bufferpixels)
3131 glt->buffermodified = false;
3132 R_UploadFullTexture(glt, glt->bufferpixels);
3141 void R_ClearTexture (rtexture_t *rt)
3143 gltexture_t *glt = (gltexture_t *)rt;
3145 R_UploadFullTexture(glt, NULL);
3148 int R_PicmipForFlags(int flags)
3151 if(flags & TEXF_PICMIP)
3153 miplevel += gl_picmip.integer;
3154 if (flags & TEXF_ISWORLD)
3156 if (r_picmipworld.integer)
3157 miplevel += gl_picmip_world.integer;
3161 else if (flags & TEXF_ISSPRITE)
3163 if (r_picmipsprites.integer)
3164 miplevel += gl_picmip_sprites.integer;
3169 miplevel += gl_picmip_other.integer;
3171 return max(0, miplevel);