File: Image.h

package info (click to toggle)
dhewm3 1.5.1~pre%2Bgit20200905%2Bdfsg-1
  • links: PTS, VCS
  • area: contrib
  • in suites: bullseye
  • size: 21,664 kB
  • sloc: cpp: 408,868; ansic: 1,188; objc: 1,034; python: 330; sh: 94; makefile: 11
file content (503 lines) | stat: -rw-r--r-- 19,854 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
/*
===========================================================================

Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.

This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").

Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.

If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.

===========================================================================
*/

#ifndef __IMAGE_H__
#define __IMAGE_H__

#include "idlib/containers/List.h"
#include "framework/FileSystem.h"
#include "renderer/Material.h"
#include "renderer/qgl.h"

/*
====================================================================

IMAGE

idImage have a one to one correspondance with OpenGL textures.

No texture is ever used that does not have a corresponding idImage.

no code outside this unit should call any of these OpenGL functions:

qglGenTextures
qglDeleteTextures
qglBindTexture

qglTexParameter

qglTexImage
qglTexSubImage

qglCopyTexImage
qglCopyTexSubImage

qglEnable( GL_TEXTURE_* )
qglDisable( GL_TEXTURE_* )

====================================================================
*/

typedef enum {
	IS_UNLOADED,	// no gl texture number
	IS_PARTIAL,		// has a texture number and the low mip levels loaded
	IS_LOADED		// has a texture number and the full mip hierarchy
} imageState_t;

static const int	MAX_TEXTURE_LEVELS = 14;

// surface description flags
const unsigned int DDSF_CAPS           = 0x00000001l;
const unsigned int DDSF_HEIGHT         = 0x00000002l;
const unsigned int DDSF_WIDTH          = 0x00000004l;
const unsigned int DDSF_PITCH          = 0x00000008l;
const unsigned int DDSF_PIXELFORMAT    = 0x00001000l;
const unsigned int DDSF_MIPMAPCOUNT    = 0x00020000l;
const unsigned int DDSF_LINEARSIZE     = 0x00080000l;
const unsigned int DDSF_DEPTH          = 0x00800000l;

// pixel format flags
const unsigned int DDSF_ALPHAPIXELS    = 0x00000001l;
const unsigned int DDSF_FOURCC         = 0x00000004l;
const unsigned int DDSF_RGB            = 0x00000040l;
const unsigned int DDSF_RGBA           = 0x00000041l;

// our extended flags
const unsigned int DDSF_ID_INDEXCOLOR	= 0x10000000l;
const unsigned int DDSF_ID_MONOCHROME	= 0x20000000l;

// dwCaps1 flags
const unsigned int DDSF_COMPLEX         = 0x00000008l;
const unsigned int DDSF_TEXTURE         = 0x00001000l;
const unsigned int DDSF_MIPMAP          = 0x00400000l;

#define DDS_MAKEFOURCC(a, b, c, d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))

typedef struct {
	unsigned int dwSize;
	unsigned int dwFlags;
	unsigned int dwFourCC;
	unsigned int dwRGBBitCount;
	unsigned int dwRBitMask;
	unsigned int dwGBitMask;
	unsigned int dwBBitMask;
	unsigned int dwABitMask;
} ddsFilePixelFormat_t;

typedef struct
{
	unsigned int dwSize;
	unsigned int dwFlags;
	unsigned int dwHeight;
	unsigned int dwWidth;
	unsigned int dwPitchOrLinearSize;
	unsigned int dwDepth;
	unsigned int dwMipMapCount;
	unsigned int dwReserved1[11];
	ddsFilePixelFormat_t ddspf;
	unsigned int dwCaps1;
	unsigned int dwCaps2;
	unsigned int dwReserved2[3];
} ddsFileHeader_t;


// increasing numeric values imply more information is stored
typedef enum {
	TD_SPECULAR,			// may be compressed, and always zeros the alpha channel
	TD_DIFFUSE,				// may be compressed
	TD_DEFAULT,				// will use compressed formats when possible
	TD_BUMP,				// may be compressed with 8 bit lookup
	TD_HIGH_QUALITY			// either 32 bit or a component format, no loss at all
} textureDepth_t;

typedef enum {
	TT_DISABLED,
	TT_2D,
	TT_3D,
	TT_CUBIC,
	TT_RECT
} textureType_t;

typedef enum {
	CF_2D,			// not a cube map
	CF_NATIVE,		// _px, _nx, _py, etc, directly sent to GL
	CF_CAMERA		// _forward, _back, etc, rotated and flipped as needed before sending to GL
} cubeFiles_t;

#define	MAX_IMAGE_NAME	256

class idImage {
public:
				idImage();

	// Makes this image active on the current GL texture unit.
	// automatically enables or disables cube mapping or texture3D
	// May perform file loading if the image was not preloaded.
	// May start a background image read.
	void		Bind();

	// for use with fragment programs, doesn't change any enable2D/3D/cube states
	void		BindFragment();

	// deletes the texture object, but leaves the structure so it can be reloaded
	void		PurgeImage();

	// used by callback functions to specify the actual data
	// data goes from the bottom to the top line of the image, as OpenGL expects it
	// These perform an implicit Bind() on the current texture unit
	// FIXME: should we implement cinematics this way, instead of with explicit calls?
	void		GenerateImage( const byte *pic, int width, int height,
					   textureFilter_t filter, bool allowDownSize,
					   textureRepeat_t repeat, textureDepth_t depth );
	void		Generate3DImage( const byte *pic, int width, int height, int depth,
						textureFilter_t filter, bool allowDownSize,
						textureRepeat_t repeat, textureDepth_t minDepth );
	void		GenerateCubeImage( const byte *pic[6], int size,
						textureFilter_t filter, bool allowDownSize,
						textureDepth_t depth );

	void		CopyFramebuffer( int x, int y, int width, int height, bool useOversizedBuffer );

	void		CopyDepthbuffer( int x, int y, int width, int height );

	void		UploadScratch( const byte *pic, int width, int height );

	// just for resource tracking
	void		SetClassification( int tag );

	// estimates size of the GL image based on dimensions and storage type
	int			StorageSize() const;

	// print a one line summary of the image
	void		Print() const;

	// check for changed timestamp on disk and reload if necessary
	void		Reload( bool checkPrecompressed, bool force );

	void		AddReference()				{ refCount++; };

//==========================================================

	void		GetDownsize( int &scaled_width, int &scaled_height ) const;
	void		MakeDefault();	// fill with a grid pattern
	void		SetImageFilterAndRepeat() const;
	bool		ShouldImageBePartialCached();
	void		WritePrecompressedImage();
	bool		CheckPrecompressedImage( bool fullLoad );
	void		UploadPrecompressedImage( byte *data, int len );
	void		ActuallyLoadImage( bool checkForPrecompressed, bool fromBackEnd );
	void		StartBackgroundImageLoad();
	int			BitsForInternalFormat( int internalFormat ) const;
	void		UploadCompressedNormalMap( int width, int height, const byte *rgba, int mipLevel );
	GLenum		SelectInternalFormat( const byte **dataPtrs, int numDataPtrs, int width, int height,
									 textureDepth_t minimumDepth ) const;
	void		ImageProgramStringToCompressedFileName( const char *imageProg, char *fileName ) const;
	int			NumLevelsForImageSize( int width, int height ) const;

	// data commonly accessed is grouped here
	static const int TEXTURE_NOT_LOADED = -1;
	GLuint				texnum;					// gl texture binding, will be TEXTURE_NOT_LOADED if not loaded
	textureType_t		type;
	int					frameUsed;				// for texture usage in frame statistics
	int					bindCount;				// incremented each bind

	// background loading information
	idImage				*partialImage;			// shrunken, space-saving version
	bool				isPartialImage;			// true if this is pointed to by another image
	bool				backgroundLoadInProgress;	// true if another thread is reading the complete d3t file
	backgroundDownload_t	bgl;
	idImage *			bglNext;				// linked from tr.backgroundImageLoads

	// parameters that define this image
	idStr				imgName;				// game path, including extension (except for cube maps), may be an image program
	void				(*generatorFunction)( idImage *image );	// NULL for files
	bool				allowDownSize;			// this also doubles as a don't-partially-load flag
	textureFilter_t		filter;
	textureRepeat_t		repeat;
	textureDepth_t		depth;
	cubeFiles_t			cubeFiles;				// determines the naming and flipping conventions for the six images

	bool				referencedOutsideLevelLoad;
	bool				levelLoadReferenced;	// for determining if it needs to be purged
	bool				precompressedFile;		// true when it was loaded from a .d3t file
	bool				defaulted;				// true if the default image was generated because a file couldn't be loaded
	ID_TIME_T				timestamp;				// the most recent of all images used in creation, for reloadImages command

	int					imageHash;				// for identical-image checking

	int					classification;			// just for resource profiling

	// data for listImages
	int					uploadWidth, uploadHeight, uploadDepth;	// after power of two, downsample, and MAX_TEXTURE_SIZE
	int					internalFormat;

	idImage				*cacheUsagePrev, *cacheUsageNext;	// for dynamic cache purging of old images

	idImage *			hashNext;				// for hash chains to speed lookup

	int					refCount;				// overall ref count
};

ID_INLINE idImage::idImage() {
	texnum = TEXTURE_NOT_LOADED;
	partialImage = NULL;
	type = TT_DISABLED;
	isPartialImage = false;
	frameUsed = 0;
	classification = 0;
	backgroundLoadInProgress = false;
	bgl.opcode = DLTYPE_FILE;
	bgl.f = NULL;
	bglNext = NULL;
	imgName[0] = '\0';
	generatorFunction = NULL;
	allowDownSize = false;
	filter = TF_DEFAULT;
	repeat = TR_REPEAT;
	depth = TD_DEFAULT;
	cubeFiles = CF_2D;
	referencedOutsideLevelLoad = false;
	levelLoadReferenced = false;
	precompressedFile = false;
	defaulted = false;
	timestamp = 0;
	bindCount = 0;
	uploadWidth = uploadHeight = uploadDepth = 0;
	internalFormat = 0;
	cacheUsagePrev = cacheUsageNext = NULL;
	hashNext = NULL;
	refCount = 0;
}


// data is RGBA
void	R_WriteTGA( const char *filename, const byte *data, int width, int height, bool flipVertical = false );
// data is an 8 bit index into palette, which is RGB (no A)
void	R_WritePalTGA( const char *filename, const byte *data, const byte *palette, int width, int height, bool flipVertical = false );
// data is in top-to-bottom raster order unless flipVertical is set


class idImageManager {
public:
	void				Init();
	void				Shutdown();

	// If the exact combination of parameters has been asked for already, an existing
	// image will be returned, otherwise a new image will be created.
	// Be careful not to use the same image file with different filter / repeat / etc parameters
	// if possible, because it will cause a second copy to be loaded.
	// If the load fails for any reason, the image will be filled in with the default
	// grid pattern.
	// Will automatically resample non-power-of-two images and execute image programs if needed.
	idImage *			ImageFromFile( const char *name,
							 textureFilter_t filter, bool allowDownSize,
							 textureRepeat_t repeat, textureDepth_t depth, cubeFiles_t cubeMap = CF_2D );

	// look for a loaded image, whatever the parameters
	idImage *			GetImage( const char *name ) const;

	// The callback will be issued immediately, and later if images are reloaded or vid_restart
	// The callback function should call one of the idImage::Generate* functions to fill in the data
	idImage *			ImageFromFunction( const char *name, void (*generatorFunction)( idImage *image ));

	// called once a frame to allow any background loads that have been completed
	// to turn into textures.
	void				CompleteBackgroundImageLoads();

	// returns the number of bytes of image data bound in the previous frame
	int					SumOfUsedImages();

	// called each frame to allow some cvars to automatically force changes
	void				CheckCvars();

	// purges all the images before a vid_restart
	void				PurgeAllImages();

	// reloads all apropriate images after a vid_restart
	void				ReloadAllImages();

	// disable the active texture unit
	void				BindNull();

	// Mark all file based images as currently unused,
	// but don't free anything.  Calls to ImageFromFile() will
	// either mark the image as used, or create a new image without
	// loading the actual data.
	// Called only by renderSystem::BeginLevelLoad
	void				BeginLevelLoad();

	// Free all images marked as unused, and load all images that are necessary.
	// This architecture prevents us from having the union of two level's
	// worth of data present at one time.
	// Called only by renderSystem::EndLevelLoad
	void				EndLevelLoad();

	// used to clear and then write the dds conversion batch file
	void				StartBuild();
	void				FinishBuild( bool removeDups = false );
	void				AddDDSCommand( const char *cmd );

	void				PrintMemInfo( MemInfo_t *mi );

	// cvars
	static idCVar		image_roundDown;			// round bad sizes down to nearest power of two
	static idCVar		image_colorMipLevels;		// development aid to see texture mip usage
	static idCVar		image_downSize;				// controls texture downsampling
	static idCVar		image_useCompression;		// 0 = force everything to high quality
	static idCVar		image_filter;				// changes texture filtering on mipmapped images
	static idCVar		image_anisotropy;			// set the maximum texture anisotropy if available
	static idCVar		image_lodbias;				// change lod bias on mipmapped images
	static idCVar		image_useAllFormats;		// allow alpha/intensity/luminance/luminance+alpha
	static idCVar		image_usePrecompressedTextures;	// use .dds files if present
	static idCVar		image_writePrecompressedTextures; // write .dds files if necessary
	static idCVar		image_writeNormalTGA;		// debug tool to write out .tgas of the final normal maps
	static idCVar		image_writeNormalTGAPalletized;		// debug tool to write out palletized versions of the final normal maps
	static idCVar		image_writeTGA;				// debug tool to write out .tgas of the non normal maps
	static idCVar		image_useNormalCompression;	// 1 = use 256 color compression for normal maps if available, 2 = use rxgb compression
	static idCVar		image_useOffLineCompression; // will write a batch file with commands for the offline compression
	static idCVar		image_preload;				// if 0, dynamically load all images
	static idCVar		image_cacheMinK;			// maximum K of precompressed files to read at specification time,
													// the remainder will be dynamically cached
	static idCVar		image_cacheMegs;			// maximum bytes set aside for temporary loading of full-sized precompressed images
	static idCVar		image_useCache;				// 1 = do background load image caching
	static idCVar		image_showBackgroundLoads;	// 1 = print number of outstanding background loads
	static idCVar		image_forceDownSize;		// allows the ability to force a downsize
	static idCVar		image_downSizeSpecular;		// downsize specular
	static idCVar		image_downSizeSpecularLimit;// downsize specular limit
	static idCVar		image_downSizeBump;			// downsize bump maps
	static idCVar		image_downSizeBumpLimit;	// downsize bump limit
	static idCVar		image_ignoreHighQuality;	// ignore high quality on materials
	static idCVar		image_downSizeLimit;		// downsize diffuse limit

	// built-in images
	idImage *			defaultImage;
	idImage *			flatNormalMap;				// 128 128 255 in all pixels
	idImage *			ambientNormalMap;			// tr.ambientLightVector encoded in all pixels
	idImage *			rampImage;					// 0-255 in RGBA in S
	idImage *			alphaRampImage;				// 0-255 in alpha, 255 in RGB
	idImage *			alphaNotchImage;			// 2x1 texture with just 1110 and 1111 with point sampling
	idImage *			whiteImage;					// full of 0xff
	idImage *			blackImage;					// full of 0x00
	idImage *			normalCubeMapImage;			// cube map to normalize STR into RGB
	idImage *			noFalloffImage;				// all 255, but zero clamped
	idImage *			fogImage;					// increasing alpha is denser fog
	idImage *			fogEnterImage;				// adjust fogImage alpha based on terminator plane
	idImage *			cinematicImage;
	idImage *			scratchImage;
	idImage *			scratchImage2;
	idImage *			accumImage;
	idImage *			currentRenderImage;			// for SS_POST_PROCESS shaders
	idImage *			scratchCubeMapImage;
	idImage *			specularTableImage;			// 1D intensity texture with our specular function
	idImage *			specular2DTableImage;		// 2D intensity texture with our specular function with variable specularity
	idImage *			borderClampImage;			// white inside, black outside

	//--------------------------------------------------------

	idImage *			AllocImage( const char *name );
	void				SetNormalPalette();
	void				ChangeTextureFilter();

	idList<idImage*>	images;
	idStrList			ddsList;
	idHashIndex			ddsHash;

	bool				insideLevelLoad;			// don't actually load images now

	byte				originalToCompressed[256];	// maps normal maps to 8 bit textures
	byte				compressedPalette[768];		// the palette that normal maps use

	// default filter modes for images
	GLenum				textureMinFilter;
	GLenum				textureMaxFilter;
	float				textureAnisotropy;
	float				textureLODBias;

	idImage *			imageHashTable[FILE_HASH_SIZE];

	idImage *			backgroundImageLoads;		// chain of images that have background file loads active
	idImage				cacheLRU;					// head/tail of doubly linked list
	int					totalCachedImageSize;		// for determining when something should be purged

	int	numActiveBackgroundImageLoads;
	const static int MAX_BACKGROUND_IMAGE_LOADS = 8;
};

extern idImageManager	*globalImages;		// pointer to global list for the rest of the system

int MakePowerOfTwo( int num );

/*
====================================================================

IMAGEPROCESS

FIXME: make an "imageBlock" type to hold byte*,width,height?
====================================================================
*/

byte *R_Dropsample( const byte *in, int inwidth, int inheight,
							int outwidth, int outheight );
byte *R_ResampleTexture( const byte *in, int inwidth, int inheight,
							int outwidth, int outheight );
byte *R_MipMapWithAlphaSpecularity( const byte *in, int width, int height );
byte *R_MipMap( const byte *in, int width, int height, bool preserveBorder );
byte *R_MipMap3D( const byte *in, int width, int height, int depth, bool preserveBorder );

// these operate in-place on the provided pixels
void R_SetBorderTexels( byte *inBase, int width, int height, const byte border[4] );
void R_SetBorderTexels3D( byte *inBase, int width, int height, int depth, const byte border[4] );
void R_BlendOverTexture( byte *data, int pixelCount, const byte blend[4] );
void R_HorizontalFlip( byte *data, int width, int height );
void R_VerticalFlip( byte *data, int width, int height );
void R_RotatePic( byte *data, int width );

/*
====================================================================

IMAGEFILES

====================================================================
*/

void R_LoadImage( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp, bool makePowerOf2 );
// pic is in top to bottom raster format
bool R_LoadCubeImages( const char *cname, cubeFiles_t extensions, byte *pic[6], int *size, ID_TIME_T *timestamp );

/*
====================================================================

IMAGEPROGRAM

====================================================================
*/

void R_LoadImageProgram( const char *name, byte **pic, int *width, int *height, ID_TIME_T *timestamp, textureDepth_t *depth = NULL );
const char *R_ParsePastImageProgram( idLexer &src );

#endif