dhewm3/neo/renderer/Image.h
dhewg 736ec20d4d Untangle the epic precompiled.h mess
Don't include the lazy precompiled.h everywhere, only what's
required for the compilation unit.
platform.h needs to be included instead to provide all essential
defines and types.
All includes use the relative path to the neo or the game
specific root.
Move all idlib related includes from idlib/Lib.h to precompiled.h.
precompiled.h still exists for the MFC stuff in tools/.
Add some missing header guards.
2011-12-19 23:21:47 +01:00

505 lines
20 KiB
C++

/*
===========================================================================
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, bool *monochromeResult ) 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
bool isMonochrome; // so the NV20 path can use a reduced pass count
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;
isMonochrome = false;
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