1 
2 #include "quakedef.h"
3 #ifdef SUPPORTD3D
4 #include <d3d9.h>
5 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
6 #endif
7 #include "image.h"
8 #include "jpeg.h"
9 #include "image_png.h"
10 #include "intoverflow.h"
11 #include "dpsoftrast.h"
12 
13 #ifndef GL_TEXTURE_3D
14 #define GL_TEXTURE_3D				0x806F
15 #endif
16 
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"};
43 
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;
49 
50 #ifdef SUPPORTD3D
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;
58 #endif
59 
60 
61 static mempool_t *texturemempool;
62 static memexpandablearray_t texturearray;
63 
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
69 
70 typedef struct textypeinfo_s
71 {
72 	const char *name;
73 	textype_t textype;
74 	int inputbytesperpixel;
75 	int internalbytesperpixel;
76 	float glinternalbytesperpixel;
77 	int glinternalformat;
78 	int glformat;
79 	int gltype;
80 }
81 textypeinfo_t;
82 
83 #ifdef USE_GLES2
84 
85 // we use these internally even if we never deliver such data to the driver
86 #define GL_BGR					0x80E0
87 #define GL_BGRA					0x80E1
88 
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};
101 
102 // image formats:
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 };
110 #ifdef __ANDROID__
111 static textypeinfo_t textype_etc1                        = {"etc1",                     TEXTYPE_ETC1          ,  1,  3,  0.5f, GL_ETC1_RGB8_OES                         , 0                 , 0                };
112 #endif
113 #else
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         };
125 
126 // image formats:
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                };
156 #endif
157 
158 typedef enum gltexturetype_e
159 {
160 	GLTEXTURETYPE_2D,
161 	GLTEXTURETYPE_3D,
162 	GLTEXTURETYPE_CUBEMAP,
163 	GLTEXTURETYPE_TOTAL
164 }
165 gltexturetype_t;
166 
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};
170 #endif
171 static int cubemapside[6] =
172 {
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
179 };
180 
181 typedef struct gltexture_s
182 {
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
191 	void *d3dtexture;
192 	void *d3dsurface;
193 #ifdef SUPPORTD3D
194 	qboolean d3disrendertargetsurface;
195 	qboolean d3disdepthstencilsurface;
196 	int d3dformat;
197 	int d3dusage;
198 	int d3dpool;
199 	int d3daddressu;
200 	int d3daddressv;
201 	int d3daddressw;
202 	int d3dmagfilter;
203 	int d3dminfilter;
204 	int d3dmipfilter;
205 	int d3dmaxmiplevelfilter;
206 	int d3dmipmaplodbias;
207 	int d3dmaxmiplevel;
208 #endif
209 
210 	// dynamic texture stuff [11/22/2007 Black]
211 	updatecallback_t updatecallback;
212 	void *updatecallback_data;
213 	// --- [11/22/2007 Black]
214 
215 	// stores backup copy of texture for deferred texture updates (gl_nopartialtextureupdates cvar)
216 	unsigned char *bufferpixels;
217 	qboolean buffermodified;
218 
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
231 	int inputdatasize;
232 	// flags supplied to the LoadTexture function
233 	// (might be altered to remove TEXF_ALPHA), and GLTEXF_ private flags
234 	int flags;
235 	// picmip level
236 	int miplevel;
237 	// pointer to one of the textype_ structs
238 	textypeinfo_t *textype;
239 	// one of the GLTEXTURETYPE_ values
240 	int texturetype;
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
247 	int sides;
248 	// how many mipmap levels in this texture
249 	int miplevels;
250 	// bytes per pixel
251 	int bytesperpixel;
252 	// GL_RGB or GL_RGBA or GL_DEPTH_COMPONENT
253 	int glformat;
254 	// 3 or 4
255 	int glinternalformat;
256 	// GL_UNSIGNED_BYTE or GL_UNSIGNED_INT or GL_UNSIGNED_SHORT or GL_FLOAT
257 	int gltype;
258 }
259 gltexture_t;
260 
261 #define TEXTUREPOOL_SENTINEL 0xC0DEDBAD
262 
263 typedef struct gltexturepool_s
264 {
265 	unsigned int sentinel;
266 	struct gltexture_s *gltchain;
267 	struct gltexturepool_s *next;
268 }
269 gltexturepool_t;
270 
271 static gltexturepool_t *gltexturepoolchain = NULL;
272 
273 static unsigned char *resizebuffer = NULL, *colorconvertbuffer;
274 static int resizebuffersize = 0;
275 static const unsigned char *texturebuffer;
276 
R_GetTexTypeInfo(textype_t textype,int flags)277 static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags)
278 {
279 	switch(textype)
280 	{
281 #ifdef USE_GLES2
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);
285 #ifdef __ANDROID__
286 	case TEXTYPE_ETC1: return &textype_etc1;
287 #endif
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;
299 #else
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);
325 #endif
326 	default:
327 		Host_Error("R_GetTexTypeInfo: unknown texture format %i with flags %x", (int)textype, flags);
328 		break;
329 	}
330 	return NULL;
331 }
332 
333 // dynamic texture code [11/22/2007 Black]
R_MarkDirtyTexture(rtexture_t * rt)334 void R_MarkDirtyTexture(rtexture_t *rt) {
335 	gltexture_t *glt = (gltexture_t*) rt;
336 	if( !glt ) {
337 		return;
338 	}
339 
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)
342 	{
343 		// mark it as dirty, so R_RealGetTexture gets called
344 		glt->dirty = true;
345 	}
346 }
347 
R_MakeTextureDynamic(rtexture_t * rt,updatecallback_t updatecallback,void * data)348 void R_MakeTextureDynamic(rtexture_t *rt, updatecallback_t updatecallback, void *data) {
349 	gltexture_t *glt = (gltexture_t*) rt;
350 	if( !glt ) {
351 		return;
352 	}
353 
354 	glt->flags |= GLTEXF_DYNAMIC;
355 	glt->updatecallback = updatecallback;
356 	glt->updatecallback_data = data;
357 }
358 
R_UpdateDynamicTexture(gltexture_t * glt)359 static void R_UpdateDynamicTexture(gltexture_t *glt) {
360 	glt->dirty = false;
361 	if( glt->updatecallback ) {
362 		glt->updatecallback( (rtexture_t*) glt, glt->updatecallback_data );
363 	}
364 }
365 
R_PurgeTexture(rtexture_t * rt)366 void R_PurgeTexture(rtexture_t *rt)
367 {
368 	if(rt && !(((gltexture_t*) rt)->flags & TEXF_PERSISTENT)) {
369 		R_FreeTexture(rt);
370 	}
371 }
372 
R_FreeTexture(rtexture_t * rt)373 void R_FreeTexture(rtexture_t *rt)
374 {
375 	gltexture_t *glt, **gltpointer;
376 
377 	glt = (gltexture_t *)rt;
378 	if (glt == NULL)
379 		Host_Error("R_FreeTexture: texture == NULL");
380 
381 	for (gltpointer = &glt->pool->gltchain;*gltpointer && *gltpointer != glt;gltpointer = &(*gltpointer)->chain);
382 	if (*gltpointer == glt)
383 		*gltpointer = glt->chain;
384 	else
385 		Host_Error("R_FreeTexture: texture \"%s\" not linked in pool", glt->identifier);
386 
387 	R_Mesh_ClearBindingsForTexture(glt->texnum);
388 
389 	switch(vid.renderpath)
390 	{
391 	case RENDERPATH_GL11:
392 	case RENDERPATH_GL13:
393 	case RENDERPATH_GL20:
394 	case RENDERPATH_GLES1:
395 	case RENDERPATH_GLES2:
396 		if (glt->texnum)
397 		{
398 			CHECKGLERROR
399 			qglDeleteTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
400 		}
401 		if (glt->renderbuffernum)
402 		{
403 			CHECKGLERROR
404 			qglDeleteRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR
405 		}
406 		break;
407 	case RENDERPATH_D3D9:
408 #ifdef SUPPORTD3D
409 		if (glt->d3dsurface)
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);
415 		else
416 			IDirect3DTexture9_Release((IDirect3DTexture9 *)glt->d3dtexture);
417 		glt->d3dtexture = NULL;
418 		glt->d3dsurface = NULL;
419 #endif
420 		break;
421 	case RENDERPATH_D3D10:
422 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
423 		break;
424 	case RENDERPATH_D3D11:
425 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
426 		break;
427 	case RENDERPATH_SOFT:
428 		if (glt->texnum)
429 			DPSOFTRAST_Texture_Free(glt->texnum);
430 		break;
431 	}
432 
433 	if (glt->inputtexels)
434 		Mem_Free(glt->inputtexels);
435 	Mem_ExpandableArray_FreeRecord(&texturearray, glt);
436 }
437 
R_AllocTexturePool(void)438 rtexturepool_t *R_AllocTexturePool(void)
439 {
440 	gltexturepool_t *pool;
441 	if (texturemempool == NULL)
442 		return NULL;
443 	pool = (gltexturepool_t *)Mem_Alloc(texturemempool, sizeof(gltexturepool_t));
444 	if (pool == NULL)
445 		return NULL;
446 	pool->next = gltexturepoolchain;
447 	gltexturepoolchain = pool;
448 	pool->sentinel = TEXTUREPOOL_SENTINEL;
449 	return (rtexturepool_t *)pool;
450 }
451 
R_FreeTexturePool(rtexturepool_t ** rtexturepool)452 void R_FreeTexturePool(rtexturepool_t **rtexturepool)
453 {
454 	gltexturepool_t *pool, **poolpointer;
455 	if (rtexturepool == NULL)
456 		return;
457 	if (*rtexturepool == NULL)
458 		return;
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;
466 	else
467 		Host_Error("R_FreeTexturePool: pool not linked");
468 	while (pool->gltchain)
469 		R_FreeTexture((rtexture_t *)pool->gltchain);
470 	Mem_Free(pool);
471 }
472 
473 
474 typedef struct glmode_s
475 {
476 	const char *name;
477 	int minification, magnification;
478 	DPSOFTRAST_TEXTURE_FILTER dpsoftrastfilter_mipmap, dpsoftrastfilter_nomipmap;
479 }
480 glmode_t;
481 
482 static glmode_t modes[6] =
483 {
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}
490 };
491 
492 #ifdef SUPPORTD3D
493 typedef struct d3dmode_s
494 {
495 	const char *name;
496 	int m1, m2;
497 }
498 d3dmode_t;
499 
500 static d3dmode_t d3dmodes[6] =
501 {
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}
508 };
509 #endif
510 
GL_TextureMode_f(void)511 static void GL_TextureMode_f (void)
512 {
513 	int i;
514 	GLint oldbindtexnum;
515 	gltexture_t *glt;
516 	gltexturepool_t *pool;
517 
518 	if (Cmd_Argc() == 1)
519 	{
520 		Con_Printf("Texture mode is %sforced\n", gl_filter_force ? "" : "not ");
521 		for (i = 0;i < 6;i++)
522 		{
523 			if (gl_filter_min == modes[i].minification)
524 			{
525 				Con_Printf("%s\n", modes[i].name);
526 				return;
527 			}
528 		}
529 		Con_Print("current filter is unknown???\n");
530 		return;
531 	}
532 
533 	for (i = 0;i < (int)(sizeof(modes)/sizeof(*modes));i++)
534 		if (!strcasecmp (modes[i].name, Cmd_Argv(1) ) )
535 			break;
536 	if (i == 6)
537 	{
538 		Con_Print("bad filter name\n");
539 		return;
540 	}
541 
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"));
545 
546 	dpsoftrast_filter_mipmap = modes[i].dpsoftrastfilter_mipmap;
547 	dpsoftrast_filter_nomipmap = modes[i].dpsoftrastfilter_nomipmap;
548 
549 	switch(vid.renderpath)
550 	{
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?
558 		CHECKGLERROR
559 		GL_ActiveTexture(0);
560 		for (pool = gltexturepoolchain;pool;pool = pool->next)
561 		{
562 			for (glt = pool->gltchain;glt;glt = glt->chain)
563 			{
564 				// only update already uploaded images
565 				if (glt->texnum && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
566 				{
567 					oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
568 					qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
569 					if (glt->flags & TEXF_MIPMAP)
570 					{
571 						qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_min);CHECKGLERROR
572 					}
573 					else
574 					{
575 						qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MIN_FILTER, gl_filter_mag);CHECKGLERROR
576 					}
577 					qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR
578 					qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
579 				}
580 			}
581 		}
582 		break;
583 	case RENDERPATH_D3D9:
584 #ifdef SUPPORTD3D
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)
595 		{
596 			for (glt = pool->gltchain;glt;glt = glt->chain)
597 			{
598 				// only update already uploaded images
599 				if (glt->d3dtexture && !glt->d3dsurface && (gl_filter_force || !(glt->flags & (TEXF_FORCENEAREST | TEXF_FORCELINEAR))))
600 				{
601 					if (glt->flags & TEXF_MIPMAP)
602 					{
603 						glt->d3dminfilter = d3d_filter_mipmin;
604 						glt->d3dmagfilter = d3d_filter_mipmag;
605 						glt->d3dmipfilter = d3d_filter_mipmix;
606 						glt->d3dmaxmiplevelfilter = 0;
607 					}
608 					else
609 					{
610 						glt->d3dminfilter = d3d_filter_flatmin;
611 						glt->d3dmagfilter = d3d_filter_flatmag;
612 						glt->d3dmipfilter = d3d_filter_flatmix;
613 						glt->d3dmaxmiplevelfilter = 0;
614 					}
615 				}
616 			}
617 		}
618 #endif
619 		break;
620 	case RENDERPATH_D3D10:
621 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
622 		break;
623 	case RENDERPATH_D3D11:
624 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
625 		break;
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);
632 		break;
633 	}
634 }
635 
GL_Texture_CalcImageSize(int texturetype,int flags,int miplevel,int inwidth,int inheight,int indepth,int * outwidth,int * outheight,int * outdepth,int * outmiplevels)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)
637 {
638 	int picmip = 0, maxsize = 0, width2 = 1, height2 = 1, depth2 = 1, miplevels = 1;
639 
640 	switch (texturetype)
641 	{
642 	default:
643 	case GLTEXTURETYPE_2D:
644 		maxsize = vid.maxtexturesize_2d;
645 		if (flags & TEXF_PICMIP)
646 		{
647 			maxsize = bound(1, gl_max_size.integer, maxsize);
648 			picmip = miplevel;
649 		}
650 		break;
651 	case GLTEXTURETYPE_3D:
652 		maxsize = vid.maxtexturesize_3d;
653 		break;
654 	case GLTEXTURETYPE_CUBEMAP:
655 		maxsize = vid.maxtexturesize_cubemap;
656 		break;
657 	}
658 
659 	if (vid.support.arb_texture_non_power_of_two)
660 	{
661 		width2 = min(inwidth >> picmip, maxsize);
662 		height2 = min(inheight >> picmip, maxsize);
663 		depth2 = min(indepth >> picmip, maxsize);
664 	}
665 	else
666 	{
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);
673 	}
674 
675 	switch(vid.renderpath)
676 	{
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:
685 		break;
686 	case RENDERPATH_D3D9:
687 #if 0
688 		// for some reason the REF rasterizer (and hence the PIX debugger) does not like small textures...
689 		if (texturetype == GLTEXTURETYPE_2D)
690 		{
691 			width2 = max(width2, 2);
692 			height2 = max(height2, 2);
693 		}
694 #endif
695 		break;
696 	}
697 
698 	miplevels = 1;
699 	if (flags & TEXF_MIPMAP)
700 	{
701 		int extent = max(width2, max(height2, depth2));
702 		while(extent >>= 1)
703 			miplevels++;
704 	}
705 
706 	if (outwidth)
707 		*outwidth = max(1, width2);
708 	if (outheight)
709 		*outheight = max(1, height2);
710 	if (outdepth)
711 		*outdepth = max(1, depth2);
712 	if (outmiplevels)
713 		*outmiplevels = miplevels;
714 }
715 
716 
R_CalcTexelDataSize(gltexture_t * glt)717 static int R_CalcTexelDataSize (gltexture_t *glt)
718 {
719 	int width2, height2, depth2, size;
720 
721 	GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &width2, &height2, &depth2, NULL);
722 
723 	size = width2 * height2 * depth2;
724 
725 	if (glt->flags & TEXF_MIPMAP)
726 	{
727 		while (width2 > 1 || height2 > 1 || depth2 > 1)
728 		{
729 			if (width2 > 1)
730 				width2 >>= 1;
731 			if (height2 > 1)
732 				height2 >>= 1;
733 			if (depth2 > 1)
734 				depth2 >>= 1;
735 			size += width2 * height2 * depth2;
736 		}
737 	}
738 
739 	return (int)(size * glt->textype->glinternalbytesperpixel) * glt->sides;
740 }
741 
R_TextureStats_Print(qboolean printeach,qboolean printpool,qboolean printtotal)742 void R_TextureStats_Print(qboolean printeach, qboolean printpool, qboolean printtotal)
743 {
744 	int glsize;
745 	int isloaded;
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;
748 	gltexture_t *glt;
749 	gltexturepool_t *pool;
750 	if (printeach)
751 		Con_Print("glsize input loaded mip alpha name\n");
752 	for (pool = gltexturepoolchain;pool;pool = pool->next)
753 	{
754 		pooltotal = 0;
755 		pooltotalt = 0;
756 		pooltotalp = 0;
757 		poolloaded = 0;
758 		poolloadedt = 0;
759 		poolloadedp = 0;
760 		for (glt = pool->gltchain;glt;glt = glt->chain)
761 		{
762 			glsize = R_CalcTexelDataSize(glt);
763 			isloaded = glt->texnum != 0 || glt->renderbuffernum != 0 || glt->d3dtexture || glt->d3dsurface;
764 			pooltotal++;
765 			pooltotalt += glsize;
766 			pooltotalp += glt->inputdatasize;
767 			if (isloaded)
768 			{
769 				poolloaded++;
770 				poolloadedt += glsize;
771 				poolloadedp += glt->inputdatasize;
772 			}
773 			if (printeach)
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);
775 		}
776 		if (printpool)
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;
784 	}
785 	if (printtotal)
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);
787 }
788 
R_TextureStats_f(void)789 static void R_TextureStats_f(void)
790 {
791 	R_TextureStats_Print(true, true, true);
792 }
793 
r_textures_start(void)794 static void r_textures_start(void)
795 {
796 	switch(vid.renderpath)
797 	{
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
804 		CHECKGLERROR
805 		qglPixelStorei(GL_UNPACK_ALIGNMENT, 1);CHECKGLERROR
806 		qglPixelStorei(GL_PACK_ALIGNMENT, 1);CHECKGLERROR
807 		break;
808 	case RENDERPATH_D3D9:
809 		break;
810 	case RENDERPATH_D3D10:
811 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
812 		break;
813 	case RENDERPATH_D3D11:
814 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
815 		break;
816 	case RENDERPATH_SOFT:
817 		break;
818 	}
819 
820 	texturemempool = Mem_AllocPool("texture management", 0, NULL);
821 	Mem_ExpandableArray_NewArray(&texturearray, texturemempool, sizeof(gltexture_t), 512);
822 
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);
828 }
829 
r_textures_shutdown(void)830 static void r_textures_shutdown(void)
831 {
832 	rtexturepool_t *temp;
833 
834 	JPEG_CloseLibrary ();
835 
836 	while(gltexturepoolchain)
837 	{
838 		temp = (rtexturepool_t *) gltexturepoolchain;
839 		R_FreeTexturePool(&temp);
840 	}
841 
842 	resizebuffersize = 0;
843 	resizebuffer = NULL;
844 	colorconvertbuffer = NULL;
845 	texturebuffer = NULL;
846 	Mem_ExpandableArray_FreeArray(&texturearray);
847 	Mem_FreePool(&texturemempool);
848 }
849 
r_textures_newmap(void)850 static void r_textures_newmap(void)
851 {
852 }
853 
r_textures_devicelost(void)854 static void r_textures_devicelost(void)
855 {
856 	int i, endindex;
857 	gltexture_t *glt;
858 	endindex = (int)Mem_ExpandableArray_IndexRange(&texturearray);
859 	for (i = 0;i < endindex;i++)
860 	{
861 		glt = (gltexture_t *) Mem_ExpandableArray_RecordAtIndex(&texturearray, i);
862 		if (!glt || !(glt->flags & TEXF_RENDERTARGET))
863 			continue;
864 		switch(vid.renderpath)
865 		{
866 		case RENDERPATH_GL11:
867 		case RENDERPATH_GL13:
868 		case RENDERPATH_GL20:
869 		case RENDERPATH_GLES1:
870 		case RENDERPATH_GLES2:
871 			break;
872 		case RENDERPATH_D3D9:
873 #ifdef SUPPORTD3D
874 			if (glt->d3dsurface)
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);
880 			else
881 				IDirect3DTexture9_Release((IDirect3DTexture9 *)glt->d3dtexture);
882 			glt->d3dtexture = NULL;
883 			glt->d3dsurface = NULL;
884 #endif
885 			break;
886 		case RENDERPATH_D3D10:
887 			Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
888 			break;
889 		case RENDERPATH_D3D11:
890 			Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
891 			break;
892 		case RENDERPATH_SOFT:
893 			break;
894 		}
895 	}
896 }
897 
r_textures_devicerestored(void)898 static void r_textures_devicerestored(void)
899 {
900 	int i, endindex;
901 	gltexture_t *glt;
902 	endindex = (int)Mem_ExpandableArray_IndexRange(&texturearray);
903 	for (i = 0;i < endindex;i++)
904 	{
905 		glt = (gltexture_t *) Mem_ExpandableArray_RecordAtIndex(&texturearray, i);
906 		if (!glt || !(glt->flags & TEXF_RENDERTARGET))
907 			continue;
908 		switch(vid.renderpath)
909 		{
910 		case RENDERPATH_GL11:
911 		case RENDERPATH_GL13:
912 		case RENDERPATH_GL20:
913 		case RENDERPATH_GLES1:
914 		case RENDERPATH_GLES2:
915 			break;
916 		case RENDERPATH_D3D9:
917 #ifdef SUPPORTD3D
918 			{
919 				HRESULT d3dresult;
920 				if (glt->d3disrendertargetsurface)
921 				{
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!");
924 				}
925 				else if (glt->d3disdepthstencilsurface)
926 				{
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!");
929 				}
930 				else if (glt->tiledepth > 1)
931 				{
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!");
934 				}
935 				else if (glt->sides == 6)
936 				{
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!");
939 				}
940 				else
941 				{
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!");
944 				}
945 			}
946 #endif
947 			break;
948 		case RENDERPATH_D3D10:
949 			Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
950 			break;
951 		case RENDERPATH_D3D11:
952 			Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
953 			break;
954 		case RENDERPATH_SOFT:
955 			break;
956 		}
957 	}
958 }
959 
960 
R_Textures_Init(void)961 void R_Textures_Init (void)
962 {
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);
991 
992 	R_RegisterModule("R_Textures", r_textures_start, r_textures_shutdown, r_textures_newmap, r_textures_devicelost, r_textures_devicerestored);
993 }
994 
R_Textures_Frame(void)995 void R_Textures_Frame (void)
996 {
997 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
998 	static int old_aniso = 0;
999 	static qboolean first_time_aniso = true;
1000 #endif
1001 
1002 	// could do procedural texture animation here, if we keep track of which
1003 	// textures were accessed this frame...
1004 
1005 	// free the resize buffers
1006 	resizebuffersize = 0;
1007 	if (resizebuffer)
1008 	{
1009 		Mem_Free(resizebuffer);
1010 		resizebuffer = NULL;
1011 	}
1012 	if (colorconvertbuffer)
1013 	{
1014 		Mem_Free(colorconvertbuffer);
1015 		colorconvertbuffer = NULL;
1016 	}
1017 
1018 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1019 	if (old_aniso != gl_texture_anisotropy.integer)
1020 	{
1021 		gltexture_t *glt;
1022 		gltexturepool_t *pool;
1023 		GLint oldbindtexnum;
1024 
1025 		old_aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
1026 
1027 		Cvar_SetValueQuick(&gl_texture_anisotropy, old_aniso);
1028 
1029 		switch(vid.renderpath)
1030 		{
1031 		case RENDERPATH_GL11:
1032 		case RENDERPATH_GL13:
1033 		case RENDERPATH_GL20:
1034 		case RENDERPATH_GLES1:
1035 		case RENDERPATH_GLES2:
1036 			// ignore the first difference, any textures loaded by now probably had the same aniso value
1037 			if (first_time_aniso)
1038 			{
1039 				first_time_aniso = false;
1040 				break;
1041 			}
1042 			CHECKGLERROR
1043 			GL_ActiveTexture(0);
1044 			for (pool = gltexturepoolchain;pool;pool = pool->next)
1045 			{
1046 				for (glt = pool->gltchain;glt;glt = glt->chain)
1047 				{
1048 					// only update already uploaded images
1049 					if (glt->texnum && (glt->flags & TEXF_MIPMAP) == TEXF_MIPMAP)
1050 					{
1051 						oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
1052 
1053 						qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
1054 						qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_ANISOTROPY_EXT, old_aniso);CHECKGLERROR
1055 
1056 						qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
1057 					}
1058 				}
1059 			}
1060 			break;
1061 		case RENDERPATH_D3D9:
1062 		case RENDERPATH_D3D10:
1063 		case RENDERPATH_D3D11:
1064 		case RENDERPATH_SOFT:
1065 			break;
1066 		}
1067 	}
1068 #endif
1069 }
1070 
R_MakeResizeBufferBigger(int size)1071 static void R_MakeResizeBufferBigger(int size)
1072 {
1073 	if (resizebuffersize < size)
1074 	{
1075 		resizebuffersize = size;
1076 		if (resizebuffer)
1077 			Mem_Free(resizebuffer);
1078 		if (colorconvertbuffer)
1079 			Mem_Free(colorconvertbuffer);
1080 		resizebuffer = (unsigned char *)Mem_Alloc(texturemempool, resizebuffersize);
1081 		colorconvertbuffer = (unsigned char *)Mem_Alloc(texturemempool, resizebuffersize);
1082 		if (!resizebuffer || !colorconvertbuffer)
1083 			Host_Error("R_Upload: out of memory");
1084 	}
1085 }
1086 
GL_SetupTextureParameters(int flags,textype_t textype,int texturetype)1087 static void GL_SetupTextureParameters(int flags, textype_t textype, int texturetype)
1088 {
1089 	int textureenum = gltexturetypeenums[texturetype];
1090 	int wrapmode = (flags & TEXF_CLAMP) ? GL_CLAMP_TO_EDGE : GL_REPEAT;
1091 
1092 	CHECKGLERROR
1093 
1094 #ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
1095 	if (vid.support.ext_texture_filter_anisotropic && (flags & TEXF_MIPMAP))
1096 	{
1097 		int aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy);
1098 		if (gl_texture_anisotropy.integer != aniso)
1099 			Cvar_SetValueQuick(&gl_texture_anisotropy, aniso);
1100 		qglTexParameteri(textureenum, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);CHECKGLERROR
1101 	}
1102 #endif
1103 	qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode);CHECKGLERROR
1104 	qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode);CHECKGLERROR
1105 #ifdef GL_TEXTURE_WRAP_R
1106 	if (gltexturetypedimensions[texturetype] >= 3)
1107 	{
1108 		qglTexParameteri(textureenum, GL_TEXTURE_WRAP_R, wrapmode);CHECKGLERROR
1109 	}
1110 #endif
1111 
1112 	CHECKGLERROR
1113 	if (!gl_filter_force && flags & TEXF_FORCENEAREST)
1114 	{
1115 		if (flags & TEXF_MIPMAP)
1116 		{
1117 			qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);CHECKGLERROR
1118 		}
1119 		else
1120 		{
1121 			qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_NEAREST);CHECKGLERROR
1122 		}
1123 		qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, GL_NEAREST);CHECKGLERROR
1124 	}
1125 	else if (!gl_filter_force && flags & TEXF_FORCELINEAR)
1126 	{
1127 		if (flags & TEXF_MIPMAP)
1128 		{
1129 			if (gl_filter_min == GL_NEAREST_MIPMAP_LINEAR || gl_filter_min == GL_LINEAR_MIPMAP_LINEAR)
1130 			{
1131 				qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);CHECKGLERROR
1132 			}
1133 			else
1134 			{
1135 				qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);CHECKGLERROR
1136 			}
1137 		}
1138 		else
1139 		{
1140 			qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, GL_LINEAR);CHECKGLERROR
1141 		}
1142 		qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, GL_LINEAR);CHECKGLERROR
1143 	}
1144 	else
1145 	{
1146 		if (flags & TEXF_MIPMAP)
1147 		{
1148 			qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_min);CHECKGLERROR
1149 		}
1150 		else
1151 		{
1152 			qglTexParameteri(textureenum, GL_TEXTURE_MIN_FILTER, gl_filter_mag);CHECKGLERROR
1153 		}
1154 		qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR
1155 	}
1156 
1157 #ifdef GL_TEXTURE_COMPARE_MODE_ARB
1158 	switch(textype)
1159 	{
1160 	case TEXTYPE_SHADOWMAP16_COMP:
1161 	case TEXTYPE_SHADOWMAP24_COMP:
1162 		qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);CHECKGLERROR
1163 		qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
1164 		qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
1165 		break;
1166 	case TEXTYPE_SHADOWMAP16_RAW:
1167 	case TEXTYPE_SHADOWMAP24_RAW:
1168 		qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);CHECKGLERROR
1169 		qglTexParameteri(textureenum, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);CHECKGLERROR
1170 		qglTexParameteri(textureenum, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);CHECKGLERROR
1171 		break;
1172 	default:
1173 		break;
1174 	}
1175 #endif
1176 
1177 	CHECKGLERROR
1178 }
1179 
R_UploadPartialTexture(gltexture_t * glt,const unsigned char * data,int fragx,int fragy,int fragz,int fragwidth,int fragheight,int fragdepth)1180 static void R_UploadPartialTexture(gltexture_t *glt, const unsigned char *data, int fragx, int fragy, int fragz, int fragwidth, int fragheight, int fragdepth)
1181 {
1182 	if (data == NULL)
1183 		Sys_Error("R_UploadPartialTexture \"%s\": partial update with NULL pixels", glt->identifier);
1184 
1185 	if (glt->texturetype != GLTEXTURETYPE_2D)
1186 		Sys_Error("R_UploadPartialTexture \"%s\": partial update of type other than 2D", glt->identifier);
1187 
1188 	if (glt->textype->textype == TEXTYPE_PALETTE)
1189 		Sys_Error("R_UploadPartialTexture \"%s\": partial update of paletted texture", glt->identifier);
1190 
1191 	if (glt->flags & (TEXF_MIPMAP | TEXF_PICMIP))
1192 		Sys_Error("R_UploadPartialTexture \"%s\": partial update not supported with MIPMAP or PICMIP flags", glt->identifier);
1193 
1194 	if (glt->inputwidth != glt->tilewidth || glt->inputheight != glt->tileheight || glt->tiledepth != 1)
1195 		Sys_Error("R_UploadPartialTexture \"%s\": partial update not supported with stretched or special textures", glt->identifier);
1196 
1197 	// update a portion of the image
1198 
1199 	switch(vid.renderpath)
1200 	{
1201 	case RENDERPATH_GL11:
1202 	case RENDERPATH_GL13:
1203 	case RENDERPATH_GL20:
1204 	case RENDERPATH_GLES1:
1205 	case RENDERPATH_GLES2:
1206 		{
1207 			int oldbindtexnum;
1208 			CHECKGLERROR
1209 			// we need to restore the texture binding after finishing the upload
1210 			GL_ActiveTexture(0);
1211 			oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
1212 			qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
1213 			qglTexSubImage2D(GL_TEXTURE_2D, 0, fragx, fragy, fragwidth, fragheight, glt->glformat, glt->gltype, data);CHECKGLERROR
1214 			qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
1215 		}
1216 		break;
1217 	case RENDERPATH_D3D9:
1218 #ifdef SUPPORTD3D
1219 		{
1220 			RECT d3drect;
1221 			D3DLOCKED_RECT d3dlockedrect;
1222 			int y;
1223 			memset(&d3drect, 0, sizeof(d3drect));
1224 			d3drect.left = fragx;
1225 			d3drect.top = fragy;
1226 			d3drect.right = fragx+fragwidth;
1227 			d3drect.bottom = fragy+fragheight;
1228 			if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, 0, &d3dlockedrect, &d3drect, 0) == D3D_OK && d3dlockedrect.pBits)
1229 			{
1230 				for (y = 0;y < fragheight;y++)
1231 					memcpy((unsigned char *)d3dlockedrect.pBits + d3dlockedrect.Pitch * y, data + fragwidth*glt->bytesperpixel * y, fragwidth*glt->bytesperpixel);
1232 				IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, 0);
1233 			}
1234 		}
1235 #endif
1236 		break;
1237 	case RENDERPATH_D3D10:
1238 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1239 		break;
1240 	case RENDERPATH_D3D11:
1241 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1242 		break;
1243 	case RENDERPATH_SOFT:
1244 		DPSOFTRAST_Texture_UpdatePartial(glt->texnum, 0, data, fragx, fragy, fragwidth, fragheight);
1245 		break;
1246 	}
1247 }
1248 
R_UploadFullTexture(gltexture_t * glt,const unsigned char * data)1249 static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data)
1250 {
1251 	int i, mip = 0, width, height, depth;
1252 	GLint oldbindtexnum = 0;
1253 	const unsigned char *prevbuffer;
1254 	prevbuffer = data;
1255 
1256 	// error out if a stretch is needed on special texture types
1257 	if (glt->texturetype != GLTEXTURETYPE_2D && (glt->tilewidth != glt->inputwidth || glt->tileheight != glt->inputheight || glt->tiledepth != glt->inputdepth))
1258 		Sys_Error("R_UploadFullTexture \"%s\": stretch uploads allowed only on 2D textures\n", glt->identifier);
1259 
1260 	// when picmip or maxsize is applied, we scale up to a power of 2 multiple
1261 	// of the target size and then use the mipmap reduction function to get
1262 	// high quality supersampled results
1263 	for (width  = glt->tilewidth;width  < glt->inputwidth ;width  <<= 1);
1264 	for (height = glt->tileheight;height < glt->inputheight;height <<= 1);
1265 	for (depth  = glt->tiledepth;depth  < glt->inputdepth ;depth  <<= 1);
1266 
1267 	if (prevbuffer == NULL)
1268 	{
1269 		width = glt->tilewidth;
1270 		height = glt->tileheight;
1271 		depth = glt->tiledepth;
1272 //		R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1273 //		memset(resizebuffer, 0, width * height * depth * glt->sides * glt->bytesperpixel);
1274 //		prevbuffer = resizebuffer;
1275 	}
1276 	else
1277 	{
1278 		if (glt->textype->textype == TEXTYPE_PALETTE)
1279 		{
1280 			// promote paletted to BGRA, so we only have to worry about BGRA in the rest of this code
1281 			R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1282 			Image_Copy8bitBGRA(prevbuffer, colorconvertbuffer, glt->inputwidth * glt->inputheight * glt->inputdepth * glt->sides, glt->palette);
1283 			prevbuffer = colorconvertbuffer;
1284 		}
1285 		if (glt->flags & TEXF_RGBMULTIPLYBYALPHA)
1286 		{
1287 			// multiply RGB channels by A channel before uploading
1288 			int alpha;
1289 			R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1290 			for (i = 0;i < glt->inputwidth*glt->inputheight*glt->inputdepth*4;i += 4)
1291 			{
1292 				alpha = prevbuffer[i+3];
1293 				colorconvertbuffer[i] = (prevbuffer[i] * alpha) >> 8;
1294 				colorconvertbuffer[i+1] = (prevbuffer[i+1] * alpha) >> 8;
1295 				colorconvertbuffer[i+2] = (prevbuffer[i+2] * alpha) >> 8;
1296 				colorconvertbuffer[i+3] = alpha;
1297 			}
1298 			prevbuffer = colorconvertbuffer;
1299 		}
1300 		// scale up to a power of 2 size (if appropriate)
1301 		if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1302 		{
1303 			R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1304 			Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1305 			prevbuffer = resizebuffer;
1306 		}
1307 		// apply mipmap reduction algorithm to get down to picmip/max_size
1308 		while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1309 		{
1310 			R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1311 			Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1312 			prevbuffer = resizebuffer;
1313 		}
1314 	}
1315 
1316 	// do the appropriate upload type...
1317 	switch(vid.renderpath)
1318 	{
1319 	case RENDERPATH_GL11:
1320 	case RENDERPATH_GL13:
1321 	case RENDERPATH_GL20:
1322 	case RENDERPATH_GLES1:
1323 	case RENDERPATH_GLES2:
1324 		if (glt->texnum) // not renderbuffers
1325 		{
1326 			CHECKGLERROR
1327 
1328 			// we need to restore the texture binding after finishing the upload
1329 			GL_ActiveTexture(0);
1330 			oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
1331 			qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
1332 
1333 #ifndef USE_GLES2
1334 #ifdef GL_TEXTURE_COMPRESSION_HINT_ARB
1335 			if (qglGetCompressedTexImageARB)
1336 			{
1337 				if (gl_texturecompression.integer >= 2)
1338 					qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_NICEST);
1339 				else
1340 					qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_FASTEST);
1341 				CHECKGLERROR
1342 			}
1343 #endif
1344 #endif
1345 			switch(glt->texturetype)
1346 			{
1347 			case GLTEXTURETYPE_2D:
1348 				qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1349 				if (glt->flags & TEXF_MIPMAP)
1350 				{
1351 					while (width > 1 || height > 1 || depth > 1)
1352 					{
1353 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1354 						Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1355 						prevbuffer = resizebuffer;
1356 						qglTexImage2D(GL_TEXTURE_2D, mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1357 					}
1358 				}
1359 				break;
1360 			case GLTEXTURETYPE_3D:
1361 #ifndef USE_GLES2
1362 				qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1363 				if (glt->flags & TEXF_MIPMAP)
1364 				{
1365 					while (width > 1 || height > 1 || depth > 1)
1366 					{
1367 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1368 						Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1369 						prevbuffer = resizebuffer;
1370 						qglTexImage3D(GL_TEXTURE_3D, mip++, glt->glinternalformat, width, height, depth, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1371 					}
1372 				}
1373 #endif
1374 				break;
1375 			case GLTEXTURETYPE_CUBEMAP:
1376 				// convert and upload each side in turn,
1377 				// from a continuous block of input texels
1378 				texturebuffer = (unsigned char *)prevbuffer;
1379 				for (i = 0;i < 6;i++)
1380 				{
1381 					prevbuffer = texturebuffer;
1382 					texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
1383 					if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1384 					{
1385 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1386 						Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1387 						prevbuffer = resizebuffer;
1388 					}
1389 					// picmip/max_size
1390 					while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1391 					{
1392 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1393 						Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1394 						prevbuffer = resizebuffer;
1395 					}
1396 					mip = 0;
1397 					qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1398 					if (glt->flags & TEXF_MIPMAP)
1399 					{
1400 						while (width > 1 || height > 1 || depth > 1)
1401 						{
1402 							R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1403 							Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1404 							prevbuffer = resizebuffer;
1405 							qglTexImage2D(cubemapside[i], mip++, glt->glinternalformat, width, height, 0, glt->glformat, glt->gltype, prevbuffer);CHECKGLERROR
1406 						}
1407 					}
1408 				}
1409 				break;
1410 			}
1411 			GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
1412 			qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
1413 		}
1414 		break;
1415 	case RENDERPATH_D3D9:
1416 #ifdef SUPPORTD3D
1417 		if (!(glt->flags & TEXF_RENDERTARGET) && glt->d3dtexture && !glt->d3dsurface)
1418 		{
1419 			D3DLOCKED_RECT d3dlockedrect;
1420 			D3DLOCKED_BOX d3dlockedbox;
1421 			switch(glt->texturetype)
1422 			{
1423 			case GLTEXTURETYPE_2D:
1424 				if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1425 				{
1426 					if (prevbuffer)
1427 						memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1428 					else
1429 						memset(d3dlockedrect.pBits, 255, width*height*glt->bytesperpixel);
1430 					IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
1431 				}
1432 				mip++;
1433 				if ((glt->flags & TEXF_MIPMAP) && prevbuffer)
1434 				{
1435 					while (width > 1 || height > 1 || depth > 1)
1436 					{
1437 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1438 						Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1439 						prevbuffer = resizebuffer;
1440 						if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1441 						{
1442 							memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1443 							IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
1444 						}
1445 						mip++;
1446 					}
1447 				}
1448 				break;
1449 			case GLTEXTURETYPE_3D:
1450 				if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits)
1451 				{
1452 					// we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes
1453 					memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel);
1454 					IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip);
1455 				}
1456 				mip++;
1457 				if (glt->flags & TEXF_MIPMAP)
1458 				{
1459 					while (width > 1 || height > 1 || depth > 1)
1460 					{
1461 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1462 						Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1463 						prevbuffer = resizebuffer;
1464 						if (IDirect3DVolumeTexture9_LockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip, &d3dlockedbox, NULL, 0) == D3D_OK && d3dlockedbox.pBits)
1465 						{
1466 							// we are not honoring the RowPitch or SlicePitch, hopefully this works with all sizes
1467 							memcpy(d3dlockedbox.pBits, prevbuffer, width*height*depth*glt->bytesperpixel);
1468 							IDirect3DVolumeTexture9_UnlockBox((IDirect3DVolumeTexture9*)glt->d3dtexture, mip);
1469 						}
1470 						mip++;
1471 					}
1472 				}
1473 				break;
1474 			case GLTEXTURETYPE_CUBEMAP:
1475 				// convert and upload each side in turn,
1476 				// from a continuous block of input texels
1477 				texturebuffer = (unsigned char *)prevbuffer;
1478 				for (i = 0;i < 6;i++)
1479 				{
1480 					prevbuffer = texturebuffer;
1481 					texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
1482 					if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1483 					{
1484 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1485 						Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1486 						prevbuffer = resizebuffer;
1487 					}
1488 					// picmip/max_size
1489 					while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1490 					{
1491 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1492 						Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1493 						prevbuffer = resizebuffer;
1494 					}
1495 					mip = 0;
1496 					if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1497 					{
1498 						memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1499 						IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip);
1500 					}
1501 					mip++;
1502 					if (glt->flags & TEXF_MIPMAP)
1503 					{
1504 						while (width > 1 || height > 1 || depth > 1)
1505 						{
1506 							R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1507 							Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, 1, 1, 1);
1508 							prevbuffer = resizebuffer;
1509 							if (IDirect3DCubeTexture9_LockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
1510 							{
1511 								memcpy(d3dlockedrect.pBits, prevbuffer, width*height*glt->bytesperpixel);
1512 								IDirect3DCubeTexture9_UnlockRect((IDirect3DCubeTexture9*)glt->d3dtexture, (D3DCUBEMAP_FACES)i, mip);
1513 							}
1514 							mip++;
1515 						}
1516 					}
1517 				}
1518 				break;
1519 			}
1520 		}
1521 		glt->d3daddressw = 0;
1522 		if (glt->flags & TEXF_CLAMP)
1523 		{
1524 			glt->d3daddressu = D3DTADDRESS_CLAMP;
1525 			glt->d3daddressv = D3DTADDRESS_CLAMP;
1526 			if (glt->tiledepth > 1)
1527 				glt->d3daddressw = D3DTADDRESS_CLAMP;
1528 		}
1529 		else
1530 		{
1531 			glt->d3daddressu = D3DTADDRESS_WRAP;
1532 			glt->d3daddressv = D3DTADDRESS_WRAP;
1533 			if (glt->tiledepth > 1)
1534 				glt->d3daddressw = D3DTADDRESS_WRAP;
1535 		}
1536 		glt->d3dmipmaplodbias = 0;
1537 		glt->d3dmaxmiplevel = 0;
1538 		glt->d3dmaxmiplevelfilter = d3d_filter_nomip ? 0 : glt->d3dmaxmiplevel;
1539 		if (glt->flags & TEXF_FORCELINEAR)
1540 		{
1541 			glt->d3dminfilter = D3DTEXF_LINEAR;
1542 			glt->d3dmagfilter = D3DTEXF_LINEAR;
1543 			glt->d3dmipfilter = D3DTEXF_POINT;
1544 		}
1545 		else if (glt->flags & TEXF_FORCENEAREST)
1546 		{
1547 			glt->d3dminfilter = D3DTEXF_POINT;
1548 			glt->d3dmagfilter = D3DTEXF_POINT;
1549 			glt->d3dmipfilter = D3DTEXF_POINT;
1550 		}
1551 		else if (glt->flags & TEXF_MIPMAP)
1552 		{
1553 			glt->d3dminfilter = d3d_filter_mipmin;
1554 			glt->d3dmagfilter = d3d_filter_mipmag;
1555 			glt->d3dmipfilter = d3d_filter_mipmix;
1556 		}
1557 		else
1558 		{
1559 			glt->d3dminfilter = d3d_filter_flatmin;
1560 			glt->d3dmagfilter = d3d_filter_flatmag;
1561 			glt->d3dmipfilter = d3d_filter_flatmix;
1562 		}
1563 #endif
1564 		break;
1565 	case RENDERPATH_D3D10:
1566 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1567 		break;
1568 	case RENDERPATH_D3D11:
1569 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1570 		break;
1571 	case RENDERPATH_SOFT:
1572 		switch(glt->texturetype)
1573 		{
1574 		case GLTEXTURETYPE_2D:
1575 			DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
1576 			break;
1577 		case GLTEXTURETYPE_3D:
1578 			DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
1579 			break;
1580 		case GLTEXTURETYPE_CUBEMAP:
1581 			if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1582 			{
1583 				unsigned char *combinedbuffer = (unsigned char *)Mem_Alloc(tempmempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
1584 				// convert and upload each side in turn,
1585 				// from a continuous block of input texels
1586 				// copy the results into combinedbuffer
1587 				texturebuffer = (unsigned char *)prevbuffer;
1588 				for (i = 0;i < 6;i++)
1589 				{
1590 					prevbuffer = texturebuffer;
1591 					texturebuffer += glt->inputwidth * glt->inputheight * glt->inputdepth * glt->textype->inputbytesperpixel;
1592 					if (glt->inputwidth != width || glt->inputheight != height || glt->inputdepth != depth)
1593 					{
1594 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1595 						Image_Resample32(prevbuffer, glt->inputwidth, glt->inputheight, glt->inputdepth, resizebuffer, width, height, depth, r_lerpimages.integer);
1596 						prevbuffer = resizebuffer;
1597 					}
1598 					// picmip/max_size
1599 					while (width > glt->tilewidth || height > glt->tileheight || depth > glt->tiledepth)
1600 					{
1601 						R_MakeResizeBufferBigger(width * height * depth * glt->sides * glt->bytesperpixel);
1602 						Image_MipReduce32(prevbuffer, resizebuffer, &width, &height, &depth, glt->tilewidth, glt->tileheight, glt->tiledepth);
1603 						prevbuffer = resizebuffer;
1604 					}
1605 					memcpy(combinedbuffer + i*glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel, prevbuffer, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->bytesperpixel);
1606 				}
1607 				DPSOFTRAST_Texture_UpdateFull(glt->texnum, combinedbuffer);
1608 				Mem_Free(combinedbuffer);
1609 			}
1610 			else
1611 				DPSOFTRAST_Texture_UpdateFull(glt->texnum, prevbuffer);
1612 			break;
1613 		}
1614 		if (glt->flags & TEXF_FORCELINEAR)
1615 			DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
1616 		else if (glt->flags & TEXF_FORCENEAREST)
1617 			DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
1618 		else if (glt->flags & TEXF_MIPMAP)
1619 			DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
1620 		else
1621 			DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
1622 		break;
1623 	}
1624 }
1625 
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)1626 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)
1627 {
1628 	int i, size;
1629 	gltexture_t *glt;
1630 	gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
1631 	textypeinfo_t *texinfo, *texinfo2;
1632 	unsigned char *temppixels = NULL;
1633 	qboolean swaprb;
1634 
1635 	if (cls.state == ca_dedicated)
1636 		return NULL;
1637 
1638 	// see if we need to swap red and blue (BGRA <-> RGBA conversion)
1639 	if (textype == TEXTYPE_PALETTE && vid.forcetextype == TEXTYPE_RGBA)
1640 	{
1641 		int numpixels = width * height * depth * sides;
1642 		size = numpixels * 4;
1643 		temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
1644 		if (data)
1645 		{
1646 			const unsigned char *p;
1647 			unsigned char *o = temppixels;
1648 			for (i = 0;i < numpixels;i++, o += 4)
1649 			{
1650 				p = (const unsigned char *)palette + 4*data[i];
1651 				o[0] = p[2];
1652 				o[1] = p[1];
1653 				o[2] = p[0];
1654 				o[3] = p[3];
1655 			}
1656 		}
1657 		data = temppixels;
1658 		textype = TEXTYPE_RGBA;
1659 	}
1660 	swaprb = false;
1661 	switch(textype)
1662 	{
1663 	case TEXTYPE_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_BGRA;} break;
1664 	case TEXTYPE_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_RGBA;} break;
1665 	case TEXTYPE_SRGB_RGBA: if (vid.forcetextype == TEXTYPE_BGRA) {swaprb = true;textype = TEXTYPE_SRGB_BGRA;} break;
1666 	case TEXTYPE_SRGB_BGRA: if (vid.forcetextype == TEXTYPE_RGBA) {swaprb = true;textype = TEXTYPE_SRGB_RGBA;} break;
1667 	default: break;
1668 	}
1669 	if (swaprb)
1670 	{
1671 		// swap bytes
1672 		static int rgbaswapindices[4] = {2, 1, 0, 3};
1673 		size = width * height * depth * sides * 4;
1674 		temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
1675 		if (data)
1676 			Image_CopyMux(temppixels, data, width, height*depth*sides, false, false, false, 4, 4, rgbaswapindices);
1677 		data = temppixels;
1678 	}
1679 
1680 	// if sRGB texture formats are not supported, convert input to linear and upload as normal types
1681 	if (!vid.support.ext_texture_srgb)
1682 	{
1683 		qboolean convertsRGB = false;
1684 		switch(textype)
1685 		{
1686 		case TEXTYPE_SRGB_DXT1:    textype = TEXTYPE_DXT1   ;convertsRGB = true;break;
1687 		case TEXTYPE_SRGB_DXT1A:   textype = TEXTYPE_DXT1A  ;convertsRGB = true;break;
1688 		case TEXTYPE_SRGB_DXT3:    textype = TEXTYPE_DXT3   ;convertsRGB = true;break;
1689 		case TEXTYPE_SRGB_DXT5:    textype = TEXTYPE_DXT5   ;convertsRGB = true;break;
1690 		case TEXTYPE_SRGB_PALETTE: textype = TEXTYPE_PALETTE;/*convertsRGB = true;*/break;
1691 		case TEXTYPE_SRGB_RGBA:    textype = TEXTYPE_RGBA   ;convertsRGB = true;break;
1692 		case TEXTYPE_SRGB_BGRA:    textype = TEXTYPE_BGRA   ;convertsRGB = true;break;
1693 		default:
1694 			break;
1695 		}
1696 		if (convertsRGB && data)
1697 		{
1698 			size = width * height * depth * sides * 4;
1699 			if (!temppixels)
1700 			{
1701 				temppixels = (unsigned char *)Mem_Alloc(tempmempool, size);
1702 				memcpy(temppixels, data, size);
1703 				data = temppixels;
1704 			}
1705 			Image_MakeLinearColorsFromsRGB(temppixels, temppixels, width*height*depth*sides);
1706 		}
1707 	}
1708 
1709 	if (texturetype == GLTEXTURETYPE_CUBEMAP && !vid.support.arb_texture_cube_map)
1710 	{
1711 		Con_Printf ("R_LoadTexture: cubemap texture not supported by driver\n");
1712 		return NULL;
1713 	}
1714 	if (texturetype == GLTEXTURETYPE_3D && !vid.support.ext_texture_3d)
1715 	{
1716 		Con_Printf ("R_LoadTexture: 3d texture not supported by driver\n");
1717 		return NULL;
1718 	}
1719 
1720 	texinfo = R_GetTexTypeInfo(textype, flags);
1721 	size = width * height * depth * sides * texinfo->inputbytesperpixel;
1722 	if (size < 1)
1723 	{
1724 		Con_Printf ("R_LoadTexture: bogus texture size (%dx%dx%dx%dbppx%dsides = %d bytes)\n", width, height, depth, texinfo->inputbytesperpixel * 8, sides, size);
1725 		return NULL;
1726 	}
1727 
1728 	// clear the alpha flag if the texture has no transparent pixels
1729 	switch(textype)
1730 	{
1731 	case TEXTYPE_PALETTE:
1732 	case TEXTYPE_SRGB_PALETTE:
1733 		if (flags & TEXF_ALPHA)
1734 		{
1735 			flags &= ~TEXF_ALPHA;
1736 			if (data)
1737 			{
1738 				for (i = 0;i < size;i++)
1739 				{
1740 					if (((unsigned char *)&palette[data[i]])[3] < 255)
1741 					{
1742 						flags |= TEXF_ALPHA;
1743 						break;
1744 					}
1745 				}
1746 			}
1747 		}
1748 		break;
1749 	case TEXTYPE_RGBA:
1750 	case TEXTYPE_BGRA:
1751 	case TEXTYPE_SRGB_RGBA:
1752 	case TEXTYPE_SRGB_BGRA:
1753 		if (flags & TEXF_ALPHA)
1754 		{
1755 			flags &= ~TEXF_ALPHA;
1756 			if (data)
1757 			{
1758 				for (i = 3;i < size;i += 4)
1759 				{
1760 					if (data[i] < 255)
1761 					{
1762 						flags |= TEXF_ALPHA;
1763 						break;
1764 					}
1765 				}
1766 			}
1767 		}
1768 		break;
1769 	case TEXTYPE_SHADOWMAP16_COMP:
1770 	case TEXTYPE_SHADOWMAP16_RAW:
1771 	case TEXTYPE_SHADOWMAP24_COMP:
1772 	case TEXTYPE_SHADOWMAP24_RAW:
1773 		break;
1774 	case TEXTYPE_DXT1:
1775 	case TEXTYPE_SRGB_DXT1:
1776 		break;
1777 	case TEXTYPE_DXT1A:
1778 	case TEXTYPE_SRGB_DXT1A:
1779 	case TEXTYPE_DXT3:
1780 	case TEXTYPE_SRGB_DXT3:
1781 	case TEXTYPE_DXT5:
1782 	case TEXTYPE_SRGB_DXT5:
1783 		flags |= TEXF_ALPHA;
1784 		break;
1785 	case TEXTYPE_ALPHA:
1786 		flags |= TEXF_ALPHA;
1787 		break;
1788 	case TEXTYPE_COLORBUFFER:
1789 	case TEXTYPE_COLORBUFFER16F:
1790 	case TEXTYPE_COLORBUFFER32F:
1791 		flags |= TEXF_ALPHA;
1792 		break;
1793 	default:
1794 		Sys_Error("R_LoadTexture: unknown texture type");
1795 	}
1796 
1797 	texinfo2 = R_GetTexTypeInfo(textype, flags);
1798 	if(size == width * height * depth * sides * texinfo->inputbytesperpixel)
1799 		texinfo = texinfo2;
1800 	else
1801 		Con_Printf ("R_LoadTexture: input size changed after alpha fallback\n");
1802 
1803 	glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
1804 	if (identifier)
1805 		strlcpy (glt->identifier, identifier, sizeof(glt->identifier));
1806 	glt->pool = pool;
1807 	glt->chain = pool->gltchain;
1808 	pool->gltchain = glt;
1809 	glt->inputwidth = width;
1810 	glt->inputheight = height;
1811 	glt->inputdepth = depth;
1812 	glt->flags = flags;
1813 	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
1814 	glt->textype = texinfo;
1815 	glt->texturetype = texturetype;
1816 	glt->inputdatasize = size;
1817 	glt->palette = palette;
1818 	glt->glinternalformat = texinfo->glinternalformat;
1819 	glt->glformat = texinfo->glformat;
1820 	glt->gltype = texinfo->gltype;
1821 	glt->bytesperpixel = texinfo->internalbytesperpixel;
1822 	glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
1823 	glt->texnum = 0;
1824 	glt->dirty = false;
1825 	glt->glisdepthstencil = false;
1826 	glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
1827 	// init the dynamic texture attributes, too [11/22/2007 Black]
1828 	glt->updatecallback = NULL;
1829 	glt->updatecallback_data = NULL;
1830 
1831 	GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth, &glt->miplevels);
1832 
1833 	// upload the texture
1834 	// data may be NULL (blank texture for dynamic rendering)
1835 	switch(vid.renderpath)
1836 	{
1837 	case RENDERPATH_GL11:
1838 	case RENDERPATH_GL13:
1839 	case RENDERPATH_GL20:
1840 	case RENDERPATH_GLES1:
1841 	case RENDERPATH_GLES2:
1842 		CHECKGLERROR
1843 		qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
1844 		break;
1845 	case RENDERPATH_D3D9:
1846 #ifdef SUPPORTD3D
1847 		{
1848 			D3DFORMAT d3dformat;
1849 			D3DPOOL d3dpool;
1850 			DWORD d3dusage;
1851 			HRESULT d3dresult;
1852 			d3dusage = 0;
1853 			d3dpool = D3DPOOL_MANAGED;
1854 			if (flags & TEXF_RENDERTARGET)
1855 			{
1856 				d3dusage |= D3DUSAGE_RENDERTARGET;
1857 				d3dpool = D3DPOOL_DEFAULT;
1858 			}
1859 			switch(textype)
1860 			{
1861 			case TEXTYPE_PALETTE: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
1862 			case TEXTYPE_RGBA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8B8G8R8 : D3DFMT_X8B8G8R8;break;
1863 			case TEXTYPE_BGRA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
1864 			case TEXTYPE_COLORBUFFER: d3dformat = D3DFMT_A8R8G8B8;break;
1865 			case TEXTYPE_COLORBUFFER16F: d3dformat = D3DFMT_A16B16G16R16F;break;
1866 			case TEXTYPE_COLORBUFFER32F: d3dformat = D3DFMT_A32B32G32R32F;break;
1867 			case TEXTYPE_ALPHA: d3dformat = D3DFMT_A8;break;
1868 			default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTexture: unsupported texture type %i when picking D3DFMT", (int)textype);break;
1869 			}
1870 			glt->d3dformat = d3dformat;
1871 			glt->d3dusage = d3dusage;
1872 			glt->d3dpool = d3dpool;
1873 			glt->d3disrendertargetsurface = false;
1874 			glt->d3disdepthstencilsurface = false;
1875 			if (glt->tiledepth > 1)
1876 			{
1877 				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)))
1878 					Sys_Error("IDirect3DDevice9_CreateVolumeTexture failed!");
1879 			}
1880 			else if (glt->sides == 6)
1881 			{
1882 				if (FAILED(d3dresult = IDirect3DDevice9_CreateCubeTexture(vid_d3d9dev, glt->tilewidth, glt->miplevels, glt->d3dusage, (D3DFORMAT)glt->d3dformat, (D3DPOOL)glt->d3dpool, (IDirect3DCubeTexture9 **)&glt->d3dtexture, NULL)))
1883 					Sys_Error("IDirect3DDevice9_CreateCubeTexture failed!");
1884 			}
1885 			else
1886 			{
1887 				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)))
1888 					Sys_Error("IDirect3DDevice9_CreateTexture failed!");
1889 			}
1890 		}
1891 #endif
1892 		break;
1893 	case RENDERPATH_D3D10:
1894 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1895 		break;
1896 	case RENDERPATH_D3D11:
1897 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1898 		break;
1899 	case RENDERPATH_SOFT:
1900 		{
1901 			int tflags = 0;
1902 			switch(textype)
1903 			{
1904 			case TEXTYPE_PALETTE: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
1905 			case TEXTYPE_RGBA: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA8;break;
1906 			case TEXTYPE_BGRA: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
1907 			case TEXTYPE_COLORBUFFER: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8;break;
1908 			case TEXTYPE_COLORBUFFER16F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA16F;break;
1909 			case TEXTYPE_COLORBUFFER32F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA32F;break;
1910 			case TEXTYPE_SHADOWMAP16_COMP:
1911 			case TEXTYPE_SHADOWMAP16_RAW:
1912 			case TEXTYPE_SHADOWMAP24_COMP:
1913 			case TEXTYPE_SHADOWMAP24_RAW: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
1914 			case TEXTYPE_DEPTHBUFFER16:
1915 			case TEXTYPE_DEPTHBUFFER24:
1916 			case TEXTYPE_DEPTHBUFFER24STENCIL8: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
1917 			case TEXTYPE_ALPHA: tflags = DPSOFTRAST_TEXTURE_FORMAT_ALPHA8;break;
1918 			default: Sys_Error("R_LoadTexture: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
1919 			}
1920 			if (glt->miplevels > 1) tflags |= DPSOFTRAST_TEXTURE_FLAG_MIPMAP;
1921 			if (flags & TEXF_ALPHA) tflags |= DPSOFTRAST_TEXTURE_FLAG_USEALPHA;
1922 			if (glt->sides == 6) tflags |= DPSOFTRAST_TEXTURE_FLAG_CUBEMAP;
1923 			if (glt->flags & TEXF_CLAMP) tflags |= DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;
1924 			glt->texnum = DPSOFTRAST_Texture_New(tflags, glt->tilewidth, glt->tileheight, glt->tiledepth);
1925 		}
1926 		break;
1927 	}
1928 
1929 	R_UploadFullTexture(glt, data);
1930 	if ((glt->flags & TEXF_ALLOWUPDATES) && gl_nopartialtextureupdates.integer)
1931 		glt->bufferpixels = (unsigned char *)Mem_Alloc(texturemempool, glt->tilewidth*glt->tileheight*glt->tiledepth*glt->sides*glt->bytesperpixel);
1932 
1933 	// free any temporary processing buffer we allocated...
1934 	if (temppixels)
1935 		Mem_Free(temppixels);
1936 
1937 	// texture converting and uploading can take a while, so make sure we're sending keepalives
1938 	// FIXME: this causes rendering during R_Shadow_DrawLights
1939 //	CL_KeepaliveMessage(false);
1940 
1941 	return (rtexture_t *)glt;
1942 }
1943 
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)1944 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)
1945 {
1946 	return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, flags, miplevel, textype, GLTEXTURETYPE_2D, data, palette);
1947 }
1948 
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)1949 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)
1950 {
1951 	return R_SetupTexture(rtexturepool, identifier, width, height, depth, 1, flags, miplevel, textype, GLTEXTURETYPE_3D, data, palette);
1952 }
1953 
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)1954 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)
1955 {
1956 	return R_SetupTexture(rtexturepool, identifier, width, width, 1, 6, flags, miplevel, textype, GLTEXTURETYPE_CUBEMAP, data, palette);
1957 }
1958 
R_LoadTextureShadowMap2D(rtexturepool_t * rtexturepool,const char * identifier,int width,int height,textype_t textype,qboolean filter)1959 rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype, qboolean filter)
1960 {
1961 	return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, TEXF_RENDERTARGET | TEXF_CLAMP | (filter ? TEXF_FORCELINEAR : TEXF_FORCENEAREST), -1, textype, GLTEXTURETYPE_2D, NULL, NULL);
1962 }
1963 
R_LoadTextureRenderBuffer(rtexturepool_t * rtexturepool,const char * identifier,int width,int height,textype_t textype)1964 rtexture_t *R_LoadTextureRenderBuffer(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, textype_t textype)
1965 {
1966 	gltexture_t *glt;
1967 	gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
1968 	textypeinfo_t *texinfo;
1969 
1970 	if (cls.state == ca_dedicated)
1971 		return NULL;
1972 
1973 	texinfo = R_GetTexTypeInfo(textype, TEXF_RENDERTARGET | TEXF_CLAMP);
1974 
1975 	glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
1976 	if (identifier)
1977 		strlcpy (glt->identifier, identifier, sizeof(glt->identifier));
1978 	glt->pool = pool;
1979 	glt->chain = pool->gltchain;
1980 	pool->gltchain = glt;
1981 	glt->inputwidth = width;
1982 	glt->inputheight = height;
1983 	glt->inputdepth = 1;
1984 	glt->flags = TEXF_RENDERTARGET | TEXF_CLAMP | TEXF_FORCENEAREST;
1985 	glt->miplevel = 0;
1986 	glt->textype = texinfo;
1987 	glt->texturetype = textype;
1988 	glt->inputdatasize = width*height*texinfo->internalbytesperpixel;
1989 	glt->palette = NULL;
1990 	glt->glinternalformat = texinfo->glinternalformat;
1991 	glt->glformat = texinfo->glformat;
1992 	glt->gltype = texinfo->gltype;
1993 	glt->bytesperpixel = texinfo->internalbytesperpixel;
1994 	glt->sides = glt->texturetype == GLTEXTURETYPE_CUBEMAP ? 6 : 1;
1995 	glt->texnum = 0;
1996 	glt->dirty = false;
1997 	glt->glisdepthstencil = textype == TEXTYPE_DEPTHBUFFER24STENCIL8;
1998 	glt->gltexturetypeenum = GL_TEXTURE_2D;
1999 	// init the dynamic texture attributes, too [11/22/2007 Black]
2000 	glt->updatecallback = NULL;
2001 	glt->updatecallback_data = NULL;
2002 
2003 	GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->miplevel, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth, &glt->miplevels);
2004 
2005 	// upload the texture
2006 	// data may be NULL (blank texture for dynamic rendering)
2007 	switch(vid.renderpath)
2008 	{
2009 	case RENDERPATH_GL11:
2010 	case RENDERPATH_GL13:
2011 	case RENDERPATH_GL20:
2012 	case RENDERPATH_GLES1:
2013 	case RENDERPATH_GLES2:
2014 		CHECKGLERROR
2015 		qglGenRenderbuffers(1, (GLuint *)&glt->renderbuffernum);CHECKGLERROR
2016 		qglBindRenderbuffer(GL_RENDERBUFFER, glt->renderbuffernum);CHECKGLERROR
2017 		qglRenderbufferStorage(GL_RENDERBUFFER, glt->glinternalformat, glt->tilewidth, glt->tileheight);CHECKGLERROR
2018 		// 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
2019 		qglBindRenderbuffer(GL_RENDERBUFFER, 0);CHECKGLERROR
2020 		break;
2021 	case RENDERPATH_D3D9:
2022 #ifdef SUPPORTD3D
2023 		{
2024 			D3DFORMAT d3dformat;
2025 			HRESULT d3dresult;
2026 			glt->d3disrendertargetsurface = false;
2027 			glt->d3disdepthstencilsurface = false;
2028 			switch(textype)
2029 			{
2030 			case TEXTYPE_COLORBUFFER: d3dformat = D3DFMT_A8R8G8B8;glt->d3disrendertargetsurface = true;break;
2031 			case TEXTYPE_COLORBUFFER16F: d3dformat = D3DFMT_A16B16G16R16F;glt->d3disrendertargetsurface = true;break;
2032 			case TEXTYPE_COLORBUFFER32F: d3dformat = D3DFMT_A32B32G32R32F;glt->d3disrendertargetsurface = true;break;
2033 			case TEXTYPE_DEPTHBUFFER16: d3dformat = D3DFMT_D16;glt->d3disdepthstencilsurface = true;break;
2034 			case TEXTYPE_DEPTHBUFFER24: d3dformat = D3DFMT_D24X8;glt->d3disdepthstencilsurface = true;break;
2035 			case TEXTYPE_DEPTHBUFFER24STENCIL8: d3dformat = D3DFMT_D24S8;glt->d3disdepthstencilsurface = true;break;
2036 			default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTextureRenderbuffer: unsupported texture type %i when picking D3DFMT", (int)textype);break;
2037 			}
2038 			glt->d3dformat = d3dformat;
2039 			glt->d3dusage = 0;
2040 			glt->d3dpool = 0;
2041 			if (glt->d3disrendertargetsurface)
2042 			{
2043 				if (FAILED(d3dresult = IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
2044 					Sys_Error("IDirect3DDevice9_CreateRenderTarget failed!");
2045 			}
2046 			else if (glt->d3disdepthstencilsurface)
2047 			{
2048 				if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dsurface, NULL)))
2049 					Sys_Error("IDirect3DDevice9_CreateDepthStencilSurface failed!");
2050 			}
2051 		}
2052 #endif
2053 		break;
2054 	case RENDERPATH_D3D10:
2055 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2056 		break;
2057 	case RENDERPATH_D3D11:
2058 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2059 		break;
2060 	case RENDERPATH_SOFT:
2061 		{
2062 			int tflags = 0;
2063 			switch(textype)
2064 			{
2065 			case TEXTYPE_COLORBUFFER: tflags = DPSOFTRAST_TEXTURE_FORMAT_BGRA8 | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2066 			case TEXTYPE_COLORBUFFER16F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA16F | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2067 			case TEXTYPE_COLORBUFFER32F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA32F | DPSOFTRAST_TEXTURE_FLAG_USEALPHA | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2068 			case TEXTYPE_DEPTHBUFFER16:
2069 			case TEXTYPE_DEPTHBUFFER24:
2070 			case TEXTYPE_DEPTHBUFFER24STENCIL8: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH | DPSOFTRAST_TEXTURE_FLAG_CLAMPTOEDGE;break;
2071 			default: Sys_Error("R_LoadTextureRenderbuffer: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
2072 			}
2073 			glt->texnum = DPSOFTRAST_Texture_New(tflags, glt->tilewidth, glt->tileheight, glt->tiledepth);
2074 		}
2075 		break;
2076 	}
2077 
2078 	return (rtexture_t *)glt;
2079 }
2080 
R_SaveTextureDDSFile(rtexture_t * rt,const char * filename,qboolean skipuncompressed,qboolean hasalpha)2081 int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha)
2082 {
2083 #ifdef USE_GLES2
2084 	return -1; // unsupported on this platform
2085 #else
2086 	gltexture_t *glt = (gltexture_t *)rt;
2087 	unsigned char *dds;
2088 	int oldbindtexnum;
2089 	int bytesperpixel = 0;
2090 	int bytesperblock = 0;
2091 	int dds_flags;
2092 	int dds_format_flags;
2093 	int dds_caps1;
2094 	int dds_caps2;
2095 	int ret;
2096 	int mip;
2097 	int mipmaps;
2098 	int mipinfo[16][4];
2099 	int ddssize = 128;
2100 	GLint internalformat;
2101 	const char *ddsfourcc;
2102 	if (!rt)
2103 		return -1; // NULL pointer
2104 	if (!strcmp(gl_version, "2.0.5885 WinXP Release"))
2105 		return -2; // broken driver - crashes on reading internal format
2106 	if (!qglGetTexLevelParameteriv)
2107 		return -2;
2108 	GL_ActiveTexture(0);
2109 	oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
2110 	qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
2111 	qglGetTexLevelParameteriv(gltexturetypeenums[glt->texturetype], 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat);
2112 	switch(internalformat)
2113 	{
2114 	default: ddsfourcc = NULL;bytesperpixel = 4;break;
2115 	case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
2116 	case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: ddsfourcc = "DXT1";bytesperblock = 8;break;
2117 	case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: ddsfourcc = "DXT3";bytesperblock = 16;break;
2118 	case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: ddsfourcc = "DXT5";bytesperblock = 16;break;
2119 	}
2120 	// if premultiplied alpha, say so in the DDS file
2121 	if(glt->flags & TEXF_RGBMULTIPLYBYALPHA)
2122 	{
2123 		switch(internalformat)
2124 		{
2125 			case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: ddsfourcc = "DXT2";break;
2126 			case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: ddsfourcc = "DXT4";break;
2127 		}
2128 	}
2129 	if (!bytesperblock && skipuncompressed)
2130 		return -3; // skipped
2131 	memset(mipinfo, 0, sizeof(mipinfo));
2132 	mipinfo[0][0] = glt->tilewidth;
2133 	mipinfo[0][1] = glt->tileheight;
2134 	mipmaps = 1;
2135 	if ((glt->flags & TEXF_MIPMAP) && !(glt->tilewidth == 1 && glt->tileheight == 1))
2136 	{
2137 		for (mip = 1;mip < 16;mip++)
2138 		{
2139 			mipinfo[mip][0] = mipinfo[mip-1][0] > 1 ? mipinfo[mip-1][0] >> 1 : 1;
2140 			mipinfo[mip][1] = mipinfo[mip-1][1] > 1 ? mipinfo[mip-1][1] >> 1 : 1;
2141 			if (mipinfo[mip][0] == 1 && mipinfo[mip][1] == 1)
2142 			{
2143 				mip++;
2144 				break;
2145 			}
2146 		}
2147 		mipmaps = mip;
2148 	}
2149 	for (mip = 0;mip < mipmaps;mip++)
2150 	{
2151 		mipinfo[mip][2] = bytesperblock ? ((mipinfo[mip][0]+3)/4)*((mipinfo[mip][1]+3)/4)*bytesperblock : mipinfo[mip][0]*mipinfo[mip][1]*bytesperpixel;
2152 		mipinfo[mip][3] = ddssize;
2153 		ddssize += mipinfo[mip][2];
2154 	}
2155 	dds = (unsigned char *)Mem_Alloc(tempmempool, ddssize);
2156 	if (!dds)
2157 		return -4;
2158 	dds_caps1 = 0x1000; // DDSCAPS_TEXTURE
2159 	dds_caps2 = 0;
2160 	if (bytesperblock)
2161 	{
2162 		dds_flags = 0x81007; // DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_LINEARSIZE
2163 		dds_format_flags = 0x4; // DDPF_FOURCC
2164 	}
2165 	else
2166 	{
2167 		dds_flags = 0x100F; // DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH
2168 		dds_format_flags = 0x40; // DDPF_RGB
2169 	}
2170 	if (mipmaps)
2171 	{
2172 		dds_flags |= 0x20000; // DDSD_MIPMAPCOUNT
2173 		dds_caps1 |= 0x400008; // DDSCAPS_MIPMAP | DDSCAPS_COMPLEX
2174 	}
2175 	if(hasalpha)
2176 		dds_format_flags |= 0x1; // DDPF_ALPHAPIXELS
2177 	memcpy(dds, "DDS ", 4);
2178 	StoreLittleLong(dds+4, 124); // http://msdn.microsoft.com/en-us/library/bb943982%28v=vs.85%29.aspx says so
2179 	StoreLittleLong(dds+8, dds_flags);
2180 	StoreLittleLong(dds+12, mipinfo[0][1]); // height
2181 	StoreLittleLong(dds+16, mipinfo[0][0]); // width
2182 	StoreLittleLong(dds+24, 0); // depth
2183 	StoreLittleLong(dds+28, mipmaps); // mipmaps
2184 	StoreLittleLong(dds+76, 32); // format size
2185 	StoreLittleLong(dds+80, dds_format_flags);
2186 	StoreLittleLong(dds+108, dds_caps1);
2187 	StoreLittleLong(dds+112, dds_caps2);
2188 	if (bytesperblock)
2189 	{
2190 		StoreLittleLong(dds+20, mipinfo[0][2]); // linear size
2191 		memcpy(dds+84, ddsfourcc, 4);
2192 		for (mip = 0;mip < mipmaps;mip++)
2193 		{
2194 			qglGetCompressedTexImageARB(gltexturetypeenums[glt->texturetype], mip, dds + mipinfo[mip][3]);CHECKGLERROR
2195 		}
2196 	}
2197 	else
2198 	{
2199 		StoreLittleLong(dds+20, mipinfo[0][0]*bytesperpixel); // pitch
2200 		StoreLittleLong(dds+88, bytesperpixel*8); // bits per pixel
2201 		dds[94] = dds[97] = dds[100] = dds[107] = 255; // bgra byte order masks
2202 		for (mip = 0;mip < mipmaps;mip++)
2203 		{
2204 			qglGetTexImage(gltexturetypeenums[glt->texturetype], mip, GL_BGRA, GL_UNSIGNED_BYTE, dds + mipinfo[mip][3]);CHECKGLERROR
2205 		}
2206 	}
2207 	qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2208 	ret = FS_WriteFile(filename, dds, ddssize);
2209 	Mem_Free(dds);
2210 	return ret ? ddssize : -5;
2211 #endif
2212 }
2213 
2214 #ifdef __ANDROID__
2215 // ELUAN: FIXME: separate this code
2216 #include "ktx10/include/ktx.h"
2217 #endif
2218 
R_LoadTextureDDSFile(rtexturepool_t * rtexturepool,const char * filename,qboolean srgb,int flags,qboolean * hasalphaflag,float * avgcolor,int miplevel,qboolean optionaltexture)2219 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
2220 {
2221 	int i, size, dds_format_flags, dds_miplevels, dds_width, dds_height;
2222 	//int dds_flags;
2223 	textype_t textype;
2224 	int bytesperblock, bytesperpixel;
2225 	int mipcomplete;
2226 	gltexture_t *glt;
2227 	gltexturepool_t *pool = (gltexturepool_t *)rtexturepool;
2228 	textypeinfo_t *texinfo;
2229 	int mip, mipwidth, mipheight, mipsize, mipsize_total;
2230 	unsigned int c, r, g, b;
2231 	GLint oldbindtexnum = 0;
2232 	unsigned char *mippixels;
2233 	unsigned char *mippixels_start;
2234 	unsigned char *ddspixels;
2235 	unsigned char *dds;
2236 	fs_offset_t ddsfilesize;
2237 	unsigned int ddssize;
2238 	qboolean force_swdecode, npothack;
2239 #ifdef __ANDROID__
2240 	// ELUAN: FIXME: separate this code
2241 	char vabuf[1024];
2242 	char vabuf2[1024];
2243 	int strsize;
2244 	KTX_dimensions sizes;
2245 #endif
2246 
2247 	if (cls.state == ca_dedicated)
2248 		return NULL;
2249 
2250 #ifdef __ANDROID__
2251 	// ELUAN: FIXME: separate this code
2252 	if (vid.renderpath != RENDERPATH_GLES2)
2253 	{
2254 		Con_DPrintf("KTX texture format is only supported on the GLES2 renderpath\n");
2255 		return NULL;
2256 	}
2257 
2258 	// some textures are specified with extensions, so it becomes .tga.dds
2259 	FS_StripExtension (filename, vabuf2, sizeof(vabuf2));
2260 	FS_StripExtension (vabuf2, vabuf, sizeof(vabuf));
2261 	FS_DefaultExtension (vabuf, ".ktx", sizeof(vabuf));
2262 	strsize = strlen(vabuf);
2263 	if (strsize > 5)
2264 	for (i = 0; i <= strsize - 4; i++) // copy null termination
2265 		vabuf[i] = vabuf[i + 4];
2266 
2267 	Con_DPrintf("Loading %s...\n", vabuf);
2268 	dds = FS_LoadFile(vabuf, tempmempool, true, &ddsfilesize);
2269 	ddssize = ddsfilesize;
2270 
2271 	if (!dds)
2272 	{
2273 		Con_DPrintf("Not found!\n");
2274 		return NULL; // not found
2275 	}
2276 	Con_DPrintf("Found!\n");
2277 
2278 	if (flags & TEXF_ALPHA)
2279 	{
2280 		Con_DPrintf("KTX texture with alpha not supported yet, disabling\n");
2281 		flags &= ~TEXF_ALPHA;
2282 	}
2283 
2284 	{
2285 		GLenum target;
2286 		GLenum glerror;
2287 		GLboolean isMipmapped;
2288 		KTX_error_code ktxerror;
2289 
2290 		glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
2291 
2292 		// texture uploading can take a while, so make sure we're sending keepalives
2293 		CL_KeepaliveMessage(false);
2294 
2295 		// create the texture object
2296 		CHECKGLERROR
2297 		GL_ActiveTexture(0);
2298 		oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[GLTEXTURETYPE_2D]);
2299 		qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
2300 		qglBindTexture(gltexturetypeenums[GLTEXTURETYPE_2D], glt->texnum);CHECKGLERROR
2301 
2302 		// upload the texture
2303 		// we need to restore the texture binding after finishing the upload
2304 
2305 		// NOTE: some drivers fail with ETC1 NPOT (only PowerVR?). This may make the driver crash later.
2306 		ktxerror = ktxLoadTextureM(dds, ddssize, &glt->texnum, &target, &sizes, &isMipmapped, &glerror,
2307 								0, NULL);// can't CHECKGLERROR, the lib catches it
2308 
2309 		// FIXME: delete texture if we fail here
2310 		if (target != GL_TEXTURE_2D)
2311 		{
2312 			qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2313 			Mem_Free(dds);
2314 			Con_DPrintf("%s target != GL_TEXTURE_2D, target == %x\n", vabuf, target);
2315 			return NULL; // FIXME: delete the texture from memory
2316 		}
2317 
2318 		if (KTX_SUCCESS == ktxerror)
2319 		{
2320 			textype = TEXTYPE_ETC1;
2321 			flags &= ~TEXF_COMPRESS; // don't let the textype be wrong
2322 
2323 			// return whether this texture is transparent
2324 			if (hasalphaflag)
2325 				*hasalphaflag = (flags & TEXF_ALPHA) != 0;
2326 
2327 			// TODO: apply gl_picmip
2328 			// TODO: avgcolor
2329 			// TODO: srgb
2330 			// TODO: only load mipmaps if requested
2331 
2332 			if (isMipmapped)
2333 				flags |= TEXF_MIPMAP;
2334 			else
2335 				flags &= ~TEXF_MIPMAP;
2336 
2337 			texinfo = R_GetTexTypeInfo(textype, flags);
2338 
2339 			strlcpy (glt->identifier, vabuf, sizeof(glt->identifier));
2340 			glt->pool = pool;
2341 			glt->chain = pool->gltchain;
2342 			pool->gltchain = glt;
2343 			glt->inputwidth = sizes.width;
2344 			glt->inputheight = sizes.height;
2345 			glt->inputdepth = 1;
2346 			glt->flags = flags;
2347 			glt->textype = texinfo;
2348 			glt->texturetype = GLTEXTURETYPE_2D;
2349 			glt->inputdatasize = ddssize;
2350 			glt->glinternalformat = texinfo->glinternalformat;
2351 			glt->glformat = texinfo->glformat;
2352 			glt->gltype = texinfo->gltype;
2353 			glt->bytesperpixel = texinfo->internalbytesperpixel;
2354 			glt->sides = 1;
2355 			glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
2356 			glt->tilewidth = sizes.width;
2357 			glt->tileheight = sizes.height;
2358 			glt->tiledepth = 1;
2359 			glt->miplevels = isMipmapped ? 1 : 0; // FIXME
2360 
2361 				// after upload we have to set some parameters...
2362 #ifdef GL_TEXTURE_MAX_LEVEL
2363 			/* FIXME
2364 				if (dds_miplevels >= 1 && !mipcomplete)
2365 				{
2366 					// need to set GL_TEXTURE_MAX_LEVEL
2367 					qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR
2368 				}
2369 			*/
2370 #endif
2371 				GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
2372 
2373 				qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2374 				Mem_Free(dds);
2375 				return (rtexture_t *)glt;
2376 		}
2377 		else
2378 		{
2379 			qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
2380 			Mem_Free(dds);
2381 			Con_DPrintf("KTX texture %s failed to load: %x\n", vabuf, ktxerror);
2382 			return NULL;
2383 		}
2384 	}
2385 #endif // __ANDROID__
2386 
2387 	dds = FS_LoadFile(filename, tempmempool, true, &ddsfilesize);
2388 	ddssize = ddsfilesize;
2389 
2390 	if (!dds)
2391 	{
2392 		if (r_texture_dds_load_logfailure.integer && (r_texture_dds_load_logfailure.integer >= 2 || !optionaltexture))
2393 			Log_Printf("ddstexturefailures.log", "%s\n", filename);
2394 		return NULL; // not found
2395 	}
2396 
2397 	if (ddsfilesize <= 128 || memcmp(dds, "DDS ", 4) || ddssize < (unsigned int)BuffLittleLong(dds+4) || BuffLittleLong(dds+76) != 32)
2398 	{
2399 		Mem_Free(dds);
2400 		Con_Printf("^1%s: not a DDS image\n", filename);
2401 		return NULL;
2402 	}
2403 
2404 	//dds_flags = BuffLittleLong(dds+8);
2405 	dds_format_flags = BuffLittleLong(dds+80);
2406 	dds_miplevels = (BuffLittleLong(dds+108) & 0x400000) ? BuffLittleLong(dds+28) : 1;
2407 	dds_width = BuffLittleLong(dds+16);
2408 	dds_height = BuffLittleLong(dds+12);
2409 	ddspixels = dds + 128;
2410 
2411 	if(r_texture_dds_load_alphamode.integer == 0)
2412 		if(!(dds_format_flags & 0x1)) // DDPF_ALPHAPIXELS
2413 			flags &= ~TEXF_ALPHA;
2414 
2415 	//flags &= ~TEXF_ALPHA; // disabled, as we DISABLE TEXF_ALPHA in the alpha detection, not enable it!
2416 	if ((dds_format_flags & 0x40) && BuffLittleLong(dds+88) == 32)
2417 	{
2418 		// very sloppy BGRA 32bit identification
2419 		textype = TEXTYPE_BGRA;
2420 		flags &= ~TEXF_COMPRESS; // don't let the textype be wrong
2421 		bytesperblock = 0;
2422 		bytesperpixel = 4;
2423 		size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(dds_width, dds_height), bytesperpixel);
2424 		if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2425 		{
2426 			Mem_Free(dds);
2427 			Con_Printf("^1%s: invalid BGRA DDS image\n", filename);
2428 			return NULL;
2429 		}
2430 		if((r_texture_dds_load_alphamode.integer == 1) && (flags & TEXF_ALPHA))
2431 		{
2432 			// check alpha
2433 			for (i = 3;i < size;i += 4)
2434 				if (ddspixels[i] < 255)
2435 					break;
2436 			if (i >= size)
2437 				flags &= ~TEXF_ALPHA;
2438 		}
2439 	}
2440 	else if (!memcmp(dds+84, "DXT1", 4))
2441 	{
2442 		// we need to find out if this is DXT1 (opaque) or DXT1A (transparent)
2443 		// LordHavoc: it is my belief that this does not infringe on the
2444 		// patent because it is not decoding pixels...
2445 		textype = TEXTYPE_DXT1;
2446 		bytesperblock = 8;
2447 		bytesperpixel = 0;
2448 		//size = ((dds_width+3)/4)*((dds_height+3)/4)*bytesperblock;
2449 		size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2450 		if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2451 		{
2452 			Mem_Free(dds);
2453 			Con_Printf("^1%s: invalid DXT1 DDS image\n", filename);
2454 			return NULL;
2455 		}
2456 		if (flags & TEXF_ALPHA)
2457 		{
2458 			if (r_texture_dds_load_alphamode.integer == 1)
2459 			{
2460 				// check alpha
2461 				for (i = 0;i < size;i += bytesperblock)
2462 					if (ddspixels[i+0] + ddspixels[i+1] * 256 <= ddspixels[i+2] + ddspixels[i+3] * 256)
2463 					{
2464 						// NOTE: this assumes sizeof(unsigned int) == 4
2465 						unsigned int data = * (unsigned int *) &(ddspixels[i+4]);
2466 						// check if data, in base 4, contains a digit 3 (DXT1: transparent pixel)
2467 						if(data & (data<<1) & 0xAAAAAAAA)//rgh
2468 							break;
2469 					}
2470 				if (i < size)
2471 					textype = TEXTYPE_DXT1A;
2472 				else
2473 					flags &= ~TEXF_ALPHA;
2474 			}
2475 			else if (r_texture_dds_load_alphamode.integer == 0)
2476 				textype = TEXTYPE_DXT1A;
2477 			else
2478 			{
2479 				flags &= ~TEXF_ALPHA;
2480 			}
2481 		}
2482 	}
2483 	else if (!memcmp(dds+84, "DXT3", 4) || !memcmp(dds+84, "DXT2", 4))
2484 	{
2485 		if(!memcmp(dds+84, "DXT2", 4))
2486 		{
2487 			if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
2488 			{
2489 				Con_Printf("^1%s: expecting DXT3 image without premultiplied alpha, got DXT2 image with premultiplied alpha\n", filename);
2490 			}
2491 		}
2492 		else
2493 		{
2494 			if(flags & TEXF_RGBMULTIPLYBYALPHA)
2495 			{
2496 				Con_Printf("^1%s: expecting DXT2 image without premultiplied alpha, got DXT3 image without premultiplied alpha\n", filename);
2497 			}
2498 		}
2499 		textype = TEXTYPE_DXT3;
2500 		bytesperblock = 16;
2501 		bytesperpixel = 0;
2502 		size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2503 		if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2504 		{
2505 			Mem_Free(dds);
2506 			Con_Printf("^1%s: invalid DXT3 DDS image\n", filename);
2507 			return NULL;
2508 		}
2509 		// we currently always assume alpha
2510 	}
2511 	else if (!memcmp(dds+84, "DXT5", 4) || !memcmp(dds+84, "DXT4", 4))
2512 	{
2513 		if(!memcmp(dds+84, "DXT4", 4))
2514 		{
2515 			if(!(flags & TEXF_RGBMULTIPLYBYALPHA))
2516 			{
2517 				Con_Printf("^1%s: expecting DXT5 image without premultiplied alpha, got DXT4 image with premultiplied alpha\n", filename);
2518 			}
2519 		}
2520 		else
2521 		{
2522 			if(flags & TEXF_RGBMULTIPLYBYALPHA)
2523 			{
2524 				Con_Printf("^1%s: expecting DXT4 image without premultiplied alpha, got DXT5 image without premultiplied alpha\n", filename);
2525 			}
2526 		}
2527 		textype = TEXTYPE_DXT5;
2528 		bytesperblock = 16;
2529 		bytesperpixel = 0;
2530 		size = INTOVERFLOW_MUL(INTOVERFLOW_MUL(INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_width, 3), 4), INTOVERFLOW_DIV(INTOVERFLOW_ADD(dds_height, 3), 4)), bytesperblock);
2531 		if(INTOVERFLOW_ADD(128, size) > INTOVERFLOW_NORMALIZE(ddsfilesize))
2532 		{
2533 			Mem_Free(dds);
2534 			Con_Printf("^1%s: invalid DXT5 DDS image\n", filename);
2535 			return NULL;
2536 		}
2537 		// we currently always assume alpha
2538 	}
2539 	else
2540 	{
2541 		Mem_Free(dds);
2542 		Con_Printf("^1%s: unrecognized/unsupported DDS format\n", filename);
2543 		return NULL;
2544 	}
2545 
2546 	// when requesting a non-alpha texture and we have DXT3/5, convert to DXT1
2547 	if(!(flags & TEXF_ALPHA) && (textype == TEXTYPE_DXT3 || textype == TEXTYPE_DXT5))
2548 	{
2549 		textype = TEXTYPE_DXT1;
2550 		bytesperblock = 8;
2551 		ddssize -= 128;
2552 		ddssize /= 2;
2553 		for (i = 0;i < (int)ddssize;i += bytesperblock)
2554 			memcpy(&ddspixels[i], &ddspixels[(i<<1)+8], 8);
2555 		ddssize += 128;
2556 	}
2557 
2558 	force_swdecode = false;
2559 	npothack =
2560 		(!vid.support.arb_texture_non_power_of_two &&
2561 			(
2562 				(dds_width & (dds_width - 1))
2563 				||
2564 				(dds_height & (dds_height - 1))
2565 			)
2566 		);
2567 	if(bytesperblock)
2568 	{
2569 		if(vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && !npothack)
2570 		{
2571 			if(r_texture_dds_swdecode.integer > 1)
2572 				force_swdecode = true;
2573 		}
2574 		else
2575 		{
2576 			if(r_texture_dds_swdecode.integer < 1)
2577 			{
2578 				// unsupported
2579 				Mem_Free(dds);
2580 				return NULL;
2581 			}
2582 			force_swdecode = true;
2583 		}
2584 	}
2585 
2586 	// return whether this texture is transparent
2587 	if (hasalphaflag)
2588 		*hasalphaflag = (flags & TEXF_ALPHA) != 0;
2589 
2590 	// if we SW decode, choose 2 sizes bigger
2591 	if(force_swdecode)
2592 	{
2593 		// this is quarter res, so do not scale down more than we have to
2594 		miplevel -= 2;
2595 
2596 		if(miplevel < 0)
2597 			Con_DPrintf("WARNING: fake software decoding of compressed texture %s degraded quality\n", filename);
2598 	}
2599 
2600 	// this is where we apply gl_picmip
2601 	mippixels_start = ddspixels;
2602 	mipwidth = dds_width;
2603 	mipheight = dds_height;
2604 	while(miplevel >= 1 && dds_miplevels >= 1)
2605 	{
2606 		if (mipwidth <= 1 && mipheight <= 1)
2607 			break;
2608 		mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2609 		mippixels_start += mipsize; // just skip
2610 		--dds_miplevels;
2611 		--miplevel;
2612 		if (mipwidth > 1)
2613 			mipwidth >>= 1;
2614 		if (mipheight > 1)
2615 			mipheight >>= 1;
2616 	}
2617 	mipsize_total = ddssize - 128 - (mippixels_start - ddspixels);
2618 	mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2619 
2620 	// from here on, we do not need the ddspixels and ddssize any more (apart from the statistics entry in glt)
2621 
2622 	// fake decode S3TC if needed
2623 	if(force_swdecode)
2624 	{
2625 		int mipsize_new = mipsize_total / bytesperblock * 4;
2626 		unsigned char *mipnewpixels = (unsigned char *) Mem_Alloc(tempmempool, mipsize_new);
2627 		unsigned char *p = mipnewpixels;
2628 		for (i = bytesperblock == 16 ? 8 : 0;i < (int)mipsize_total;i += bytesperblock, p += 4)
2629 		{
2630 			c = mippixels_start[i] + 256*mippixels_start[i+1] + 65536*mippixels_start[i+2] + 16777216*mippixels_start[i+3];
2631 			p[2] = (((c >> 11) & 0x1F) + ((c >> 27) & 0x1F)) * (0.5f / 31.0f * 255.0f);
2632 			p[1] = (((c >>  5) & 0x3F) + ((c >> 21) & 0x3F)) * (0.5f / 63.0f * 255.0f);
2633 			p[0] = (((c      ) & 0x1F) + ((c >> 16) & 0x1F)) * (0.5f / 31.0f * 255.0f);
2634 			if(textype == TEXTYPE_DXT5)
2635 				p[3] = (0.5 * mippixels_start[i-8] + 0.5 * mippixels_start[i-7]);
2636 			else if(textype == TEXTYPE_DXT3)
2637 				p[3] = (
2638 					  (mippixels_start[i-8] & 0x0F)
2639 					+ (mippixels_start[i-8] >> 4)
2640 					+ (mippixels_start[i-7] & 0x0F)
2641 					+ (mippixels_start[i-7] >> 4)
2642 					+ (mippixels_start[i-6] & 0x0F)
2643 					+ (mippixels_start[i-6] >> 4)
2644 					+ (mippixels_start[i-5] & 0x0F)
2645 					+ (mippixels_start[i-5] >> 4)
2646 				       ) * (0.125f / 15.0f * 255.0f);
2647 			else
2648 				p[3] = 255;
2649 		}
2650 
2651 		textype = TEXTYPE_BGRA;
2652 		bytesperblock = 0;
2653 		bytesperpixel = 4;
2654 
2655 		// as each block becomes a pixel, we must use pixel count for this
2656 		mipwidth = (mipwidth + 3) / 4;
2657 		mipheight = (mipheight + 3) / 4;
2658 		mipsize = bytesperpixel * mipwidth * mipheight;
2659 		mippixels_start = mipnewpixels;
2660 		mipsize_total = mipsize_new;
2661 	}
2662 
2663 	// start mip counting
2664 	mippixels = mippixels_start;
2665 
2666 	// calculate average color if requested
2667 	if (avgcolor)
2668 	{
2669 		float f;
2670 		Vector4Clear(avgcolor);
2671 		if (bytesperblock)
2672 		{
2673 			for (i = bytesperblock == 16 ? 8 : 0;i < mipsize;i += bytesperblock)
2674 			{
2675 				c = mippixels[i] + 256*mippixels[i+1] + 65536*mippixels[i+2] + 16777216*mippixels[i+3];
2676 				avgcolor[0] += ((c >> 11) & 0x1F) + ((c >> 27) & 0x1F);
2677 				avgcolor[1] += ((c >>  5) & 0x3F) + ((c >> 21) & 0x3F);
2678 				avgcolor[2] += ((c      ) & 0x1F) + ((c >> 16) & 0x1F);
2679 				if(textype == TEXTYPE_DXT5)
2680 					avgcolor[3] += (mippixels[i-8] + (int) mippixels[i-7]) * (0.5f / 255.0f);
2681 				else if(textype == TEXTYPE_DXT3)
2682 					avgcolor[3] += (
2683 						  (mippixels_start[i-8] & 0x0F)
2684 						+ (mippixels_start[i-8] >> 4)
2685 						+ (mippixels_start[i-7] & 0x0F)
2686 						+ (mippixels_start[i-7] >> 4)
2687 						+ (mippixels_start[i-6] & 0x0F)
2688 						+ (mippixels_start[i-6] >> 4)
2689 						+ (mippixels_start[i-5] & 0x0F)
2690 						+ (mippixels_start[i-5] >> 4)
2691 					       ) * (0.125f / 15.0f);
2692 				else
2693 					avgcolor[3] += 1.0f;
2694 			}
2695 			f = (float)bytesperblock / mipsize;
2696 			avgcolor[0] *= (0.5f / 31.0f) * f;
2697 			avgcolor[1] *= (0.5f / 63.0f) * f;
2698 			avgcolor[2] *= (0.5f / 31.0f) * f;
2699 			avgcolor[3] *= f;
2700 		}
2701 		else
2702 		{
2703 			for (i = 0;i < mipsize;i += 4)
2704 			{
2705 				avgcolor[0] += mippixels[i+2];
2706 				avgcolor[1] += mippixels[i+1];
2707 				avgcolor[2] += mippixels[i];
2708 				avgcolor[3] += mippixels[i+3];
2709 			}
2710 			f = (1.0f / 255.0f) * bytesperpixel / mipsize;
2711 			avgcolor[0] *= f;
2712 			avgcolor[1] *= f;
2713 			avgcolor[2] *= f;
2714 			avgcolor[3] *= f;
2715 		}
2716 	}
2717 
2718 	// if we want sRGB, convert now
2719 	if(srgb)
2720 	{
2721 		if (vid.support.ext_texture_srgb)
2722 		{
2723 			switch(textype)
2724 			{
2725 			case TEXTYPE_DXT1:    textype = TEXTYPE_SRGB_DXT1   ;break;
2726 			case TEXTYPE_DXT1A:   textype = TEXTYPE_SRGB_DXT1A  ;break;
2727 			case TEXTYPE_DXT3:    textype = TEXTYPE_SRGB_DXT3   ;break;
2728 			case TEXTYPE_DXT5:    textype = TEXTYPE_SRGB_DXT5   ;break;
2729 			case TEXTYPE_RGBA:    textype = TEXTYPE_SRGB_RGBA   ;break;
2730 			default:
2731 				break;
2732 			}
2733 		}
2734 		else
2735 		{
2736 			switch(textype)
2737 			{
2738 			case TEXTYPE_DXT1:
2739 			case TEXTYPE_DXT1A:
2740 			case TEXTYPE_DXT3:
2741 			case TEXTYPE_DXT5:
2742 				{
2743 					for (i = bytesperblock == 16 ? 8 : 0;i < mipsize_total;i += bytesperblock)
2744 					{
2745 						int c0, c1, c0new, c1new;
2746 						c0 = mippixels_start[i] + 256*mippixels_start[i+1];
2747 						r = ((c0 >> 11) & 0x1F);
2748 						g = ((c0 >>  5) & 0x3F);
2749 						b = ((c0      ) & 0x1F);
2750 						r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2751 						g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2752 						b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2753 						c0new = (r << 11) | (g << 5) | b;
2754 						c1 = mippixels_start[i+2] + 256*mippixels_start[i+3];
2755 						r = ((c1 >> 11) & 0x1F);
2756 						g = ((c1 >>  5) & 0x3F);
2757 						b = ((c1      ) & 0x1F);
2758 						r = floor(Image_LinearFloatFromsRGB(r * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2759 						g = floor(Image_LinearFloatFromsRGB(g * (255.0f / 63.0f)) * 63.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2760 						b = floor(Image_LinearFloatFromsRGB(b * (255.0f / 31.0f)) * 31.0f + 0.5f); // these multiplications here get combined with multiplications in Image_LinearFloatFromsRGB
2761 						c1new = (r << 11) | (g << 5) | b;
2762 						// swap the colors if needed to fix order
2763 						if(c0 > c1) // thirds
2764 						{
2765 							if(c0new < c1new)
2766 							{
2767 								c = c0new;
2768 								c0new = c1new;
2769 								c1new = c;
2770 								if(c0new == c1new)
2771 								mippixels_start[i+4] ^= 0x55;
2772 								mippixels_start[i+5] ^= 0x55;
2773 								mippixels_start[i+6] ^= 0x55;
2774 								mippixels_start[i+7] ^= 0x55;
2775 							}
2776 							else if(c0new == c1new)
2777 							{
2778 								mippixels_start[i+4] = 0x00;
2779 								mippixels_start[i+5] = 0x00;
2780 								mippixels_start[i+6] = 0x00;
2781 								mippixels_start[i+7] = 0x00;
2782 							}
2783 						}
2784 						else // half + transparent
2785 						{
2786 							if(c0new > c1new)
2787 							{
2788 								c = c0new;
2789 								c0new = c1new;
2790 								c1new = c;
2791 								mippixels_start[i+4] ^= (~mippixels_start[i+4] >> 1) & 0x55;
2792 								mippixels_start[i+5] ^= (~mippixels_start[i+5] >> 1) & 0x55;
2793 								mippixels_start[i+6] ^= (~mippixels_start[i+6] >> 1) & 0x55;
2794 								mippixels_start[i+7] ^= (~mippixels_start[i+7] >> 1) & 0x55;
2795 							}
2796 						}
2797 						mippixels_start[i] = c0new & 255;
2798 						mippixels_start[i+1] = c0new >> 8;
2799 						mippixels_start[i+2] = c1new & 255;
2800 						mippixels_start[i+3] = c1new >> 8;
2801 					}
2802 				}
2803 				break;
2804 			case TEXTYPE_RGBA:
2805 				Image_MakeLinearColorsFromsRGB(mippixels, mippixels, mipsize_total / bytesperblock);
2806 				break;
2807 			default:
2808 				break;
2809 			}
2810 		}
2811 	}
2812 
2813 	// when not requesting mipmaps, do not load them
2814 	if(!(flags & TEXF_MIPMAP))
2815 		dds_miplevels = 0;
2816 
2817 	if (dds_miplevels >= 1)
2818 		flags |= TEXF_MIPMAP;
2819 	else
2820 		flags &= ~TEXF_MIPMAP;
2821 
2822 	texinfo = R_GetTexTypeInfo(textype, flags);
2823 
2824 	glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray);
2825 	strlcpy (glt->identifier, filename, sizeof(glt->identifier));
2826 	glt->pool = pool;
2827 	glt->chain = pool->gltchain;
2828 	pool->gltchain = glt;
2829 	glt->inputwidth = mipwidth;
2830 	glt->inputheight = mipheight;
2831 	glt->inputdepth = 1;
2832 	glt->flags = flags;
2833 	glt->textype = texinfo;
2834 	glt->texturetype = GLTEXTURETYPE_2D;
2835 	glt->inputdatasize = ddssize;
2836 	glt->glinternalformat = texinfo->glinternalformat;
2837 	glt->glformat = texinfo->glformat;
2838 	glt->gltype = texinfo->gltype;
2839 	glt->bytesperpixel = texinfo->internalbytesperpixel;
2840 	glt->sides = 1;
2841 	glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype];
2842 	glt->tilewidth = mipwidth;
2843 	glt->tileheight = mipheight;
2844 	glt->tiledepth = 1;
2845 	glt->miplevels = dds_miplevels;
2846 
2847 	if(npothack)
2848 	{
2849 		for (glt->tilewidth = 1;glt->tilewidth < mipwidth;glt->tilewidth <<= 1);
2850 		for (glt->tileheight = 1;glt->tileheight < mipheight;glt->tileheight <<= 1);
2851 	}
2852 
2853 	// texture uploading can take a while, so make sure we're sending keepalives
2854 	CL_KeepaliveMessage(false);
2855 
2856 	// create the texture object
2857 	switch(vid.renderpath)
2858 	{
2859 	case RENDERPATH_GL11:
2860 	case RENDERPATH_GL13:
2861 	case RENDERPATH_GL20:
2862 	case RENDERPATH_GLES1:
2863 	case RENDERPATH_GLES2:
2864 		CHECKGLERROR
2865 		GL_ActiveTexture(0);
2866 		oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]);
2867 		qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR
2868 		qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR
2869 		break;
2870 	case RENDERPATH_D3D9:
2871 #ifdef SUPPORTD3D
2872 		{
2873 			D3DFORMAT d3dformat;
2874 			D3DPOOL d3dpool;
2875 			DWORD d3dusage;
2876 			switch(textype)
2877 			{
2878 			case TEXTYPE_BGRA: d3dformat = (flags & TEXF_ALPHA) ? D3DFMT_A8R8G8B8 : D3DFMT_X8R8G8B8;break;
2879 			case TEXTYPE_DXT1: case TEXTYPE_DXT1A: d3dformat = D3DFMT_DXT1;break;
2880 			case TEXTYPE_DXT3: d3dformat = D3DFMT_DXT3;break;
2881 			case TEXTYPE_DXT5: d3dformat = D3DFMT_DXT5;break;
2882 			default: d3dformat = D3DFMT_A8R8G8B8;Host_Error("R_LoadTextureDDSFile: unsupported texture type %i when picking D3DFMT", (int)textype);break;
2883 			}
2884 			d3dusage = 0;
2885 			d3dpool = D3DPOOL_MANAGED;
2886 			IDirect3DDevice9_CreateTexture(vid_d3d9dev, glt->tilewidth, glt->tileheight, glt->miplevels, d3dusage, d3dformat, d3dpool, (IDirect3DTexture9 **)&glt->d3dtexture, NULL);
2887 		}
2888 #endif
2889 		break;
2890 	case RENDERPATH_D3D10:
2891 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2892 		break;
2893 	case RENDERPATH_D3D11:
2894 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2895 		break;
2896 	case RENDERPATH_SOFT:
2897 		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);
2898 		break;
2899 	}
2900 
2901 	// upload the texture
2902 	// we need to restore the texture binding after finishing the upload
2903 	mipcomplete = false;
2904 
2905 	for (mip = 0;mip <= dds_miplevels;mip++) // <= to include the not-counted "largest" miplevel
2906 	{
2907 		unsigned char *upload_mippixels = mippixels;
2908 		int upload_mipwidth = mipwidth;
2909 		int upload_mipheight = mipheight;
2910 		mipsize = bytesperblock ? ((mipwidth+3)/4)*((mipheight+3)/4)*bytesperblock : mipwidth*mipheight*bytesperpixel;
2911 		if (mippixels + mipsize > mippixels_start + mipsize_total)
2912 			break;
2913 		if(npothack)
2914 		{
2915 			upload_mipwidth = (glt->tilewidth >> mip);
2916 			upload_mipheight = (glt->tileheight >> mip);
2917 			if(upload_mipwidth != mipwidth || upload_mipheight != mipheight)
2918 			// I _think_ they always mismatch, but I was too lazy
2919 			// to properly check, and this test here is really
2920 			// harmless
2921 			{
2922 				upload_mippixels = (unsigned char *) Mem_Alloc(tempmempool, 4 * upload_mipwidth * upload_mipheight);
2923 				Image_Resample32(mippixels, mipwidth, mipheight, 1, upload_mippixels, upload_mipwidth, upload_mipheight, 1, r_lerpimages.integer);
2924 			}
2925 		}
2926 		switch(vid.renderpath)
2927 		{
2928 		case RENDERPATH_GL11:
2929 		case RENDERPATH_GL13:
2930 		case RENDERPATH_GL20:
2931 		case RENDERPATH_GLES1:
2932 		case RENDERPATH_GLES2:
2933 			if (bytesperblock)
2934 			{
2935 				qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, mipsize, upload_mippixels);CHECKGLERROR
2936 			}
2937 			else
2938 			{
2939 				qglTexImage2D(GL_TEXTURE_2D, mip, glt->glinternalformat, upload_mipwidth, upload_mipheight, 0, glt->glformat, glt->gltype, upload_mippixels);CHECKGLERROR
2940 			}
2941 			break;
2942 		case RENDERPATH_D3D9:
2943 #ifdef SUPPORTD3D
2944 			{
2945 				D3DLOCKED_RECT d3dlockedrect;
2946 				if (IDirect3DTexture9_LockRect((IDirect3DTexture9*)glt->d3dtexture, mip, &d3dlockedrect, NULL, 0) == D3D_OK && d3dlockedrect.pBits)
2947 				{
2948 					memcpy(d3dlockedrect.pBits, upload_mippixels, mipsize);
2949 					IDirect3DTexture9_UnlockRect((IDirect3DTexture9*)glt->d3dtexture, mip);
2950 				}
2951 				break;
2952 			}
2953 #endif
2954 			break;
2955 		case RENDERPATH_D3D10:
2956 			Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2957 			break;
2958 		case RENDERPATH_D3D11:
2959 			Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2960 			break;
2961 		case RENDERPATH_SOFT:
2962 			if (bytesperblock)
2963 				Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2964 			else
2965 				DPSOFTRAST_Texture_UpdateFull(glt->texnum, upload_mippixels);
2966 			// DPSOFTRAST calculates its own mipmaps
2967 			mip = dds_miplevels;
2968 			break;
2969 		}
2970 		if(upload_mippixels != mippixels)
2971 			Mem_Free(upload_mippixels);
2972 		mippixels += mipsize;
2973 		if (mipwidth <= 1 && mipheight <= 1)
2974 		{
2975 			mipcomplete = true;
2976 			break;
2977 		}
2978 		if (mipwidth > 1)
2979 			mipwidth >>= 1;
2980 		if (mipheight > 1)
2981 			mipheight >>= 1;
2982 	}
2983 
2984 	// after upload we have to set some parameters...
2985 	switch(vid.renderpath)
2986 	{
2987 	case RENDERPATH_GL11:
2988 	case RENDERPATH_GL13:
2989 	case RENDERPATH_GL20:
2990 	case RENDERPATH_GLES1:
2991 	case RENDERPATH_GLES2:
2992 #ifdef GL_TEXTURE_MAX_LEVEL
2993 		if (dds_miplevels >= 1 && !mipcomplete)
2994 		{
2995 			// need to set GL_TEXTURE_MAX_LEVEL
2996 			qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR
2997 		}
2998 #endif
2999 		GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype);
3000 		qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR
3001 		break;
3002 	case RENDERPATH_D3D9:
3003 #ifdef SUPPORTD3D
3004 		glt->d3daddressw = 0;
3005 		if (glt->flags & TEXF_CLAMP)
3006 		{
3007 			glt->d3daddressu = D3DTADDRESS_CLAMP;
3008 			glt->d3daddressv = D3DTADDRESS_CLAMP;
3009 			if (glt->tiledepth > 1)
3010 				glt->d3daddressw = D3DTADDRESS_CLAMP;
3011 		}
3012 		else
3013 		{
3014 			glt->d3daddressu = D3DTADDRESS_WRAP;
3015 			glt->d3daddressv = D3DTADDRESS_WRAP;
3016 			if (glt->tiledepth > 1)
3017 				glt->d3daddressw = D3DTADDRESS_WRAP;
3018 		}
3019 		glt->d3dmipmaplodbias = 0;
3020 		glt->d3dmaxmiplevel = 0;
3021 		glt->d3dmaxmiplevelfilter = 0;
3022 		if (glt->flags & TEXF_MIPMAP)
3023 		{
3024 			glt->d3dminfilter = d3d_filter_mipmin;
3025 			glt->d3dmagfilter = d3d_filter_mipmag;
3026 			glt->d3dmipfilter = d3d_filter_mipmix;
3027 		}
3028 		else
3029 		{
3030 			glt->d3dminfilter = d3d_filter_flatmin;
3031 			glt->d3dmagfilter = d3d_filter_flatmag;
3032 			glt->d3dmipfilter = d3d_filter_flatmix;
3033 		}
3034 #endif
3035 		break;
3036 	case RENDERPATH_D3D10:
3037 		Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3038 		break;
3039 	case RENDERPATH_D3D11:
3040 		Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3041 		break;
3042 	case RENDERPATH_SOFT:
3043 		if (glt->flags & TEXF_FORCELINEAR)
3044 			DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_LINEAR);
3045 		else if (glt->flags & TEXF_FORCENEAREST)
3046 			DPSOFTRAST_Texture_Filter(glt->texnum, DPSOFTRAST_TEXTURE_FILTER_NEAREST);
3047 		else if (glt->flags & TEXF_MIPMAP)
3048 			DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_mipmap);
3049 		else
3050 			DPSOFTRAST_Texture_Filter(glt->texnum, dpsoftrast_filter_nomipmap);
3051 		break;
3052 	}
3053 
3054 	Mem_Free(dds);
3055 	if(force_swdecode)
3056 		Mem_Free((unsigned char *) mippixels_start);
3057 	return (rtexture_t *)glt;
3058 }
3059 
R_TextureWidth(rtexture_t * rt)3060 int R_TextureWidth(rtexture_t *rt)
3061 {
3062 	return rt ? ((gltexture_t *)rt)->inputwidth : 0;
3063 }
3064 
R_TextureHeight(rtexture_t * rt)3065 int R_TextureHeight(rtexture_t *rt)
3066 {
3067 	return rt ? ((gltexture_t *)rt)->inputheight : 0;
3068 }
3069 
R_TextureFlags(rtexture_t * rt)3070 int R_TextureFlags(rtexture_t *rt)
3071 {
3072 	return rt ? ((gltexture_t *)rt)->flags : 0;
3073 }
3074 
R_UpdateTexture(rtexture_t * rt,const unsigned char * data,int x,int y,int z,int width,int height,int depth)3075 void R_UpdateTexture(rtexture_t *rt, const unsigned char *data, int x, int y, int z, int width, int height, int depth)
3076 {
3077 	gltexture_t *glt = (gltexture_t *)rt;
3078 	if (data == NULL)
3079 		Host_Error("R_UpdateTexture: no data supplied");
3080 	if (glt == NULL)
3081 		Host_Error("R_UpdateTexture: no texture supplied");
3082 	if (!glt->texnum && !glt->d3dtexture)
3083 	{
3084 		Con_DPrintf("R_UpdateTexture: texture %p \"%s\" in pool %p has not been uploaded yet\n", (void *)glt, glt->identifier, (void *)glt->pool);
3085 		return;
3086 	}
3087 	// update part of the texture
3088 	if (glt->bufferpixels)
3089 	{
3090 		int j;
3091 		int bpp = glt->bytesperpixel;
3092 		int inputskip = width*bpp;
3093 		int outputskip = glt->tilewidth*bpp;
3094 		const unsigned char *input = data;
3095 		unsigned char *output = glt->bufferpixels;
3096 		if (glt->inputdepth != 1 || glt->sides != 1)
3097 			Sys_Error("R_UpdateTexture on buffered texture that is not 2D\n");
3098 		if (x < 0)
3099 		{
3100 			width += x;
3101 			input -= x*bpp;
3102 			x = 0;
3103 		}
3104 		if (y < 0)
3105 		{
3106 			height += y;
3107 			input -= y*inputskip;
3108 			y = 0;
3109 		}
3110 		if (width > glt->tilewidth - x)
3111 			width = glt->tilewidth - x;
3112 		if (height > glt->tileheight - y)
3113 			height = glt->tileheight - y;
3114 		if (width < 1 || height < 1)
3115 			return;
3116 		glt->dirty = true;
3117 		glt->buffermodified = true;
3118 		output += y*outputskip + x*bpp;
3119 		for (j = 0;j < height;j++, output += outputskip, input += inputskip)
3120 			memcpy(output, input, width*bpp);
3121 	}
3122 	else if (x || y || z || width != glt->inputwidth || height != glt->inputheight || depth != glt->inputdepth)
3123 		R_UploadPartialTexture(glt, data, x, y, z, width, height, depth);
3124 	else
3125 		R_UploadFullTexture(glt, data);
3126 }
3127 
R_RealGetTexture(rtexture_t * rt)3128 int R_RealGetTexture(rtexture_t *rt)
3129 {
3130 	if (rt)
3131 	{
3132 		gltexture_t *glt;
3133 		glt = (gltexture_t *)rt;
3134 		if (glt->flags & GLTEXF_DYNAMIC)
3135 			R_UpdateDynamicTexture(glt);
3136 		if (glt->buffermodified && glt->bufferpixels)
3137 		{
3138 			glt->buffermodified = false;
3139 			R_UploadFullTexture(glt, glt->bufferpixels);
3140 		}
3141 		glt->dirty = false;
3142 		return glt->texnum;
3143 	}
3144 	else
3145 		return r_texture_white->texnum;
3146 }
3147 
R_ClearTexture(rtexture_t * rt)3148 void R_ClearTexture (rtexture_t *rt)
3149 {
3150 	gltexture_t *glt = (gltexture_t *)rt;
3151 
3152 	R_UploadFullTexture(glt, NULL);
3153 }
3154 
R_PicmipForFlags(int flags)3155 int R_PicmipForFlags(int flags)
3156 {
3157 	int miplevel = 0;
3158 	if(flags & TEXF_PICMIP)
3159 	{
3160 		miplevel += gl_picmip.integer;
3161 		if (flags & TEXF_ISWORLD)
3162 		{
3163 			if (r_picmipworld.integer)
3164 				miplevel += gl_picmip_world.integer;
3165 			else
3166 				miplevel = 0;
3167 		}
3168 		else if (flags & TEXF_ISSPRITE)
3169 		{
3170 			if (r_picmipsprites.integer)
3171 				miplevel += gl_picmip_sprites.integer;
3172 			else
3173 				miplevel = 0;
3174 		}
3175 		else
3176 			miplevel += gl_picmip_other.integer;
3177 	}
3178 	return max(0, miplevel);
3179 }
3180