820 lines
29 KiB
C
820 lines
29 KiB
C
|
// Copyright (C) 2007 Id Software, Inc.
|
||
|
//
|
||
|
|
||
|
#ifndef __IMAGE_H__
|
||
|
#define __IMAGE_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_* )
|
||
|
|
||
|
====================================================================
|
||
|
*/
|
||
|
|
||
|
#include "../libs/qglLib/qgl.h"
|
||
|
|
||
|
#include "../framework/FileSystem.h"
|
||
|
#include "../renderer/RendererEnums.h"
|
||
|
|
||
|
class idCVar;
|
||
|
class idMegaTexture;
|
||
|
|
||
|
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 long DDSF_CAPS = 0x00000001l;
|
||
|
const unsigned long DDSF_HEIGHT = 0x00000002l;
|
||
|
const unsigned long DDSF_WIDTH = 0x00000004l;
|
||
|
const unsigned long DDSF_PITCH = 0x00000008l;
|
||
|
const unsigned long DDSF_PIXELFORMAT = 0x00001000l;
|
||
|
const unsigned long DDSF_MIPMAPCOUNT = 0x00020000l;
|
||
|
const unsigned long DDSF_LINEARSIZE = 0x00080000l;
|
||
|
const unsigned long DDSF_DEPTH = 0x00800000l;
|
||
|
|
||
|
// pixel format flags
|
||
|
const unsigned long DDSF_ALPHAPIXELS = 0x00000001l;
|
||
|
const unsigned long DDSF_FOURCC = 0x00000004l;
|
||
|
const unsigned long DDSF_RGB = 0x00000040l;
|
||
|
const unsigned long DDSF_RGBA = 0x00000041l;
|
||
|
|
||
|
// our extended flags
|
||
|
const unsigned long DDSF_ID_INDEXCOLOR = 0x10000000l;
|
||
|
const unsigned long DDSF_ID_MONOCHROME = 0x20000000l;
|
||
|
|
||
|
// dwCaps1 flags
|
||
|
const unsigned long DDSF_COMPLEX = 0x00000008l;
|
||
|
const unsigned long DDSF_TEXTURE = 0x00001000l;
|
||
|
const unsigned long DDSF_MIPMAP = 0x00400000l;
|
||
|
|
||
|
#define DDS_MAKEFOURCC( a, b, c, d ) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
|
||
|
|
||
|
typedef struct {
|
||
|
unsigned long dwSize;
|
||
|
unsigned long dwFlags;
|
||
|
unsigned long dwFourCC;
|
||
|
unsigned long dwRGBBitCount;
|
||
|
unsigned long dwRBitMask;
|
||
|
unsigned long dwGBitMask;
|
||
|
unsigned long dwBBitMask;
|
||
|
unsigned long dwABitMask;
|
||
|
} ddsFilePixelFormat_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
unsigned long dwSize;
|
||
|
unsigned long dwFlags;
|
||
|
unsigned long dwHeight;
|
||
|
unsigned long dwWidth;
|
||
|
unsigned long dwPitchOrLinearSize;
|
||
|
unsigned long dwDepth;
|
||
|
unsigned long dwMipMapCount;
|
||
|
unsigned long dwReserved1[11];
|
||
|
ddsFilePixelFormat_t ddspf;
|
||
|
unsigned long dwCaps1;
|
||
|
unsigned long dwCaps2;
|
||
|
unsigned long dwReserved2[3];
|
||
|
} ddsFileHeader_t;
|
||
|
|
||
|
struct mipmapState_t {
|
||
|
enum colorType_e {
|
||
|
MT_NONE,
|
||
|
MT_DEFAULT,
|
||
|
MT_WATER,
|
||
|
MT_COLORLEVELS
|
||
|
};
|
||
|
|
||
|
bool operator == ( const mipmapState_t &a ) {
|
||
|
return !memcmp( this, &a, sizeof( mipmapState_t ) );
|
||
|
}
|
||
|
|
||
|
bool operator != ( const mipmapState_t &a ) {
|
||
|
return !operator ==( a );
|
||
|
}
|
||
|
|
||
|
float color[4]; // Color to blend to
|
||
|
float blend[4]; // Blend factor for every channel
|
||
|
colorType_e colorType;
|
||
|
};
|
||
|
|
||
|
static const mipmapState_t defaultMipmapState = { {0,0,0,0}, {0,0,0,0}, mipmapState_t::MT_NONE };
|
||
|
|
||
|
#define MAX_IMAGE_NAME 256
|
||
|
|
||
|
class idImageGeneratorFunctorBase {
|
||
|
public:
|
||
|
virtual ~idImageGeneratorFunctorBase( void ) { }
|
||
|
virtual void operator()( class idImage *image ) const = 0;
|
||
|
};
|
||
|
|
||
|
template <class T> class idImageGeneratorFunctor : public idImageGeneratorFunctorBase {
|
||
|
public:
|
||
|
typedef void( T::*func_t )( class idImage *image );
|
||
|
|
||
|
void Init( T* generatorClass, func_t imageGenerator ) {
|
||
|
this->generatorClass = generatorClass;
|
||
|
this->imageGenerator = imageGenerator;
|
||
|
}
|
||
|
|
||
|
virtual void operator()( class idImage *image ) const {
|
||
|
(*generatorClass.*imageGenerator)( image );
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
T * generatorClass;
|
||
|
func_t imageGenerator;
|
||
|
};
|
||
|
|
||
|
class idImageGeneratorFunctorGlobal : public idImageGeneratorFunctorBase {
|
||
|
public:
|
||
|
typedef void( *func_t )( class idImage *image );
|
||
|
|
||
|
idImageGeneratorFunctorGlobal( func_t imageGenerator ) {
|
||
|
this->imageGenerator = imageGenerator;
|
||
|
}
|
||
|
|
||
|
virtual void operator()( class idImage *image ) const {
|
||
|
imageGenerator( image );
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
func_t imageGenerator;
|
||
|
};
|
||
|
|
||
|
class idImage {
|
||
|
public:
|
||
|
idImage();
|
||
|
|
||
|
// Makes this image active on the current GL texture unit.
|
||
|
// automatically enables or disables cube mapping or texture3D
|
||
|
virtual void Bind();
|
||
|
|
||
|
// for use with fragment programs, doesn't change any enable2D/3D/cube states
|
||
|
virtual void BindFragment();
|
||
|
virtual void BindFragment( const int imageUnit );
|
||
|
|
||
|
// deletes the texture object, but leaves the structure so it can be reloaded
|
||
|
virtual void Purge();
|
||
|
|
||
|
virtual bool IsLoaded() const;
|
||
|
|
||
|
virtual void SetMipmapLevel( byte *pixels, int width, int height, int level, mipmapState_t &state );
|
||
|
|
||
|
// 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?
|
||
|
virtual void GenerateImage( const byte *pic, int width, int height,
|
||
|
textureFilter_t filter, bool allowDownSize,
|
||
|
textureRepeat_t repeat, textureDepth_t depth, mipmapState_t mipmapState = defaultMipmapState );
|
||
|
|
||
|
virtual void GenerateImageEx( const byte *pic, int width, int height,
|
||
|
textureFilter_t filter, bool allowDownSize,
|
||
|
textureRepeat_t repeat, textureDepth_t depth,
|
||
|
int internalFormatParm = 0, int numMipLevels = -1 );
|
||
|
|
||
|
virtual void Generate3DImage( const byte *pic, int width, int height, int depth,
|
||
|
textureFilter_t filter, bool allowDownSize,
|
||
|
textureRepeat_t repeat, textureDepth_t minDepth );
|
||
|
|
||
|
virtual void GenerateCubeImage( const byte *pic[6], int size,
|
||
|
textureFilter_t filter, bool allowDownSize,
|
||
|
textureDepth_t depth );
|
||
|
|
||
|
virtual void GenerateMipmaps(); // uses hardware manual mipmap generation
|
||
|
|
||
|
void CopyFramebuffer( int x, int y, int width, int height, bool useOversizedBuffer );
|
||
|
|
||
|
void CopyFramebufferCube( int x, int y, int imageWidth, int imageHeight, int faceNum );
|
||
|
|
||
|
void CopyDepthbuffer( int x, int y, int width, int height );
|
||
|
|
||
|
void UploadScratch( const byte *pic, int width, int height );
|
||
|
|
||
|
// Copy data from one image over to the other
|
||
|
void CopyFromImage( idImage *img );
|
||
|
void CopyFromImageCube( idImage *img );
|
||
|
|
||
|
void Download( byte **pixels, 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( bool csv ) const;
|
||
|
|
||
|
// check for changed timestamp on disk and reload if necessary
|
||
|
virtual void Reload( bool checkPrecompressed, bool force );
|
||
|
|
||
|
//==========================================================
|
||
|
|
||
|
void GetDownsize( int &scaled_width, int &scaled_height ) const;
|
||
|
virtual void MakeDefault(); // fill with a grid pattern
|
||
|
#if defined( _XENON )
|
||
|
void FromParameters( int width, int height, int internalFormat, textureType_t type, textureFilter_t filter, textureRepeat_t repeat, bool linearTexture = true );
|
||
|
#else
|
||
|
void FromParameters( int width, int height, int internalFormat, textureType_t type, textureFilter_t filter, textureRepeat_t repeat );
|
||
|
#endif
|
||
|
void SetImageFilterAndRepeat() const;
|
||
|
bool CanBePartialLoaded();
|
||
|
void WritePrecompressedImage();
|
||
|
bool CheckPrecompressedImage( bool fullLoad );
|
||
|
void UploadPrecompressedImage( byte *data, int len );
|
||
|
void ActuallyLoadImage( bool checkForPrecompressed );
|
||
|
bool 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;
|
||
|
|
||
|
static int NumLevelsForImageSize( int width, int height );
|
||
|
static int NumLevelsForImageSize( int width, int height, int internalFormat );
|
||
|
static int DataSizeForImageSize( int width, int height, int internalFormat );
|
||
|
|
||
|
void SetLodDistance( float distance );
|
||
|
|
||
|
private:
|
||
|
void VerifyInternalFormat( GLenum target ) const;
|
||
|
|
||
|
public:
|
||
|
// data commonly accessed is grouped here
|
||
|
static const int TEXTURE_NOT_LOADED = 0;
|
||
|
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
|
||
|
|
||
|
//lodding information
|
||
|
bool distanceLod; // we are to far away, a lower res version can be used just fine
|
||
|
float smallestDistanceSeen; // The smallest distance seen so far for the lod parameter
|
||
|
int frameOfDistance; // The frame the lod was last set
|
||
|
|
||
|
// parameters that define this image
|
||
|
idStr imgName; // game path, including extension (except for cube maps), may be an image program
|
||
|
const idImageGeneratorFunctorBase * generatorFunction; // NULL for files
|
||
|
bool fromParams;
|
||
|
bool allowDownSize; // this also doubles as a don't-partially-load flag
|
||
|
mutable bool isMonochrome;
|
||
|
int picMipOfs;
|
||
|
int picMipMin;
|
||
|
float anisotropy;
|
||
|
textureFilter_t filter;
|
||
|
textureRepeat_t repeat;
|
||
|
textureDepth_t depth;
|
||
|
cubeFiles_t cubeFiles; // determines the naming and flipping conventions for the six images
|
||
|
mipmapState_t mipmapState; // Mipmap level coloring
|
||
|
int numMipLevels;
|
||
|
float minLod;
|
||
|
float maxLod;
|
||
|
|
||
|
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
|
||
|
unsigned 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
|
||
|
|
||
|
int sourceWidth, sourceHeight; // after power of two, before downsample
|
||
|
|
||
|
// 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
|
||
|
};
|
||
|
|
||
|
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.fh = NULL;
|
||
|
bglNext = NULL;
|
||
|
imgName[0] = '\0';
|
||
|
generatorFunction = NULL;
|
||
|
fromParams = false;
|
||
|
allowDownSize = false;
|
||
|
picMipOfs = 0;
|
||
|
picMipMin = -10;
|
||
|
anisotropy = -1.f;
|
||
|
filter = TF_DEFAULT;
|
||
|
repeat = TR_REPEAT;
|
||
|
depth = TD_DEFAULT;
|
||
|
cubeFiles = CF_2D;
|
||
|
mipmapState = defaultMipmapState;
|
||
|
numMipLevels = 0;
|
||
|
referencedOutsideLevelLoad = false;
|
||
|
levelLoadReferenced = false;
|
||
|
precompressedFile = false;
|
||
|
defaulted = false;
|
||
|
timestamp = 0;
|
||
|
bindCount = 0;
|
||
|
sourceWidth = sourceHeight = 0;
|
||
|
uploadWidth = uploadHeight = uploadDepth = 0;
|
||
|
internalFormat = 0;
|
||
|
hashNext = NULL;
|
||
|
distanceLod = false;
|
||
|
frameOfDistance = 0;
|
||
|
smallestDistanceSeen = 0.0f;
|
||
|
isMonochrome = false;
|
||
|
minLod = 0.f;
|
||
|
maxLod = 1000.f;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
idImage::NumLevelsForImageSize
|
||
|
|
||
|
FIXME: the switch statement is far from complete
|
||
|
==================
|
||
|
*/
|
||
|
ID_INLINE int idImage::NumLevelsForImageSize( int width, int height, int internalFormat ) {
|
||
|
int numLevels = 1;
|
||
|
int minSize;
|
||
|
|
||
|
switch( internalFormat ) {
|
||
|
case GL_RGBA8:
|
||
|
minSize = 1;
|
||
|
break;
|
||
|
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||
|
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||
|
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||
|
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||
|
minSize = 4;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
while ( width > minSize || height > minSize ) {
|
||
|
numLevels++;
|
||
|
width >>= 1;
|
||
|
height >>= 1;
|
||
|
}
|
||
|
|
||
|
return numLevels;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
==================
|
||
|
idImage::DataSizeForImageSize
|
||
|
|
||
|
FIXME: the switch statement is far from complete
|
||
|
==================
|
||
|
*/
|
||
|
ID_INLINE int idImage::DataSizeForImageSize( int width, int height, int internalFormat ) {
|
||
|
int numLevels = NumLevelsForImageSize( width, height, internalFormat );
|
||
|
|
||
|
int dataSize = 0;
|
||
|
|
||
|
for ( int i = 0; i < numLevels; i++ ) {
|
||
|
switch( internalFormat ) {
|
||
|
case GL_RGBA8:
|
||
|
dataSize += width * height * 4;
|
||
|
break;
|
||
|
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||
|
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||
|
assert( width == height );
|
||
|
dataSize += ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 ) * 8;
|
||
|
break;
|
||
|
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||
|
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||
|
assert( width == height );
|
||
|
dataSize += ( ( width + 3 ) / 4 ) * ( ( height + 3 ) / 4 ) * 16;
|
||
|
break;
|
||
|
default:
|
||
|
dataSize = -1;
|
||
|
}
|
||
|
|
||
|
width >>= 1;
|
||
|
height >>= 1;
|
||
|
}
|
||
|
|
||
|
return dataSize;
|
||
|
}
|
||
|
|
||
|
class idImageCopyFunctorGlobal : public idImageGeneratorFunctorGlobal {
|
||
|
public:
|
||
|
idImageCopyFunctorGlobal( func_t defaultGenerator ) :
|
||
|
idImageGeneratorFunctorGlobal( defaultGenerator ),
|
||
|
srcImage( NULL ),
|
||
|
dstImage( NULL ) { ; }
|
||
|
|
||
|
virtual void operator()( idImage *image ) const {
|
||
|
dstImage = image;
|
||
|
if ( !srcImage ) {
|
||
|
imageGenerator( dstImage );
|
||
|
} else {
|
||
|
// Set source to NULL, when we do a reloadimages this causes
|
||
|
// the (!source) case to be executed recusively first, so
|
||
|
// a new image is created and infinite recursion is avoided.
|
||
|
idImage *tempSource = srcImage;
|
||
|
srcImage = NULL;
|
||
|
dstImage->CopyFromImage( tempSource );
|
||
|
//tempSource->Purge();
|
||
|
srcImage = tempSource;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
virtual void SetSource( idImage *image ) {
|
||
|
srcImage = image;
|
||
|
if ( dstImage ) {
|
||
|
dstImage->CopyFromImage( srcImage );
|
||
|
//Do a purge since the source image is probably not going to be used directly ever
|
||
|
//source->Purge();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
mutable idImage * srcImage;
|
||
|
mutable idImage * dstImage;
|
||
|
};
|
||
|
|
||
|
struct imageParams_t {
|
||
|
textureFilter_t tf;
|
||
|
textureRepeat_t trp;
|
||
|
textureDepth_t td;
|
||
|
cubeFiles_t cubeMap;
|
||
|
mipmapState_t mipState;
|
||
|
bool allowPicmip;
|
||
|
int picmipofs;
|
||
|
int picMipMin;
|
||
|
float anisotropy;
|
||
|
bool partialLoad;
|
||
|
float minLod;
|
||
|
float maxLod;
|
||
|
|
||
|
imageParams_t::imageParams_t() {
|
||
|
Clear();
|
||
|
}
|
||
|
imageParams_t::imageParams_t( textureFilter_t _filter, bool _allowDownSize, int _picmipofs, float _anisotropy,
|
||
|
textureRepeat_t _repeat, textureDepth_t _depth, cubeFiles_t _cubeMap = CF_2D, mipmapState_t _mipmapState = defaultMipmapState ) {
|
||
|
Clear();
|
||
|
|
||
|
tf = _filter;
|
||
|
allowPicmip = _allowDownSize;
|
||
|
picmipofs = _picmipofs;
|
||
|
anisotropy = _anisotropy;
|
||
|
trp = _repeat;
|
||
|
td = _depth;
|
||
|
cubeMap = _cubeMap;
|
||
|
mipState = _mipmapState;
|
||
|
}
|
||
|
|
||
|
void Clear() {
|
||
|
tf = TF_DEFAULT;
|
||
|
trp = TR_REPEAT;
|
||
|
td = TD_DEFAULT;
|
||
|
cubeMap = CF_2D;
|
||
|
mipState = defaultMipmapState;
|
||
|
allowPicmip = true;
|
||
|
picmipofs = 0;
|
||
|
partialLoad = false;
|
||
|
anisotropy = -1.f;
|
||
|
minLod = 0.f;
|
||
|
maxLod = 1000.f;
|
||
|
picMipMin = -10;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static const imageParams_t defaultImageParms;
|
||
|
|
||
|
class idImageManager {
|
||
|
public:
|
||
|
void Init();
|
||
|
void PreSys3DShutdown();
|
||
|
void Shutdown();
|
||
|
|
||
|
bool IsInitialized() const { return ( images.Num() != 0 ); }
|
||
|
|
||
|
static idImage* ParseImage( idParser& src, const imageParams_t& defaultParms = defaultImageParms );
|
||
|
|
||
|
// 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.
|
||
|
virtual idImage * ImageFromFile( const char *name, imageParams_t params );
|
||
|
//textureFilter_t filter, bool allowDownSize, int picmipofs, float anisotropy,
|
||
|
//textureRepeat_t repeat, textureDepth_t depth, cubeFiles_t cubeMap = CF_2D, mipmapState_t mipmapState = defaultMipmapState,
|
||
|
//bool partialLoad = false );
|
||
|
|
||
|
// 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
|
||
|
virtual idImage * ImageFromFunction( const char *name, const idImageGeneratorFunctorBase & generatorFunction );
|
||
|
|
||
|
// called once a frame to allow any background loads that have been completed
|
||
|
// to turn into textures.
|
||
|
void CompleteBackgroundImageLoads();
|
||
|
|
||
|
#if defined( _XENON )
|
||
|
virtual idImage* ImageFromParameters( const char* name, int width, int height, int internalFormat, textureType_t type, textureFilter_t filter, textureRepeat_t repeat, bool linearTexture = true );
|
||
|
#else
|
||
|
virtual idImage* ImageFromParameters( const char* name, int width, int height, int internalFormat, textureType_t type, textureFilter_t filter, textureRepeat_t repeat );
|
||
|
#endif
|
||
|
|
||
|
virtual idMegaTexture* MegaTextureFromFile( const char *name );
|
||
|
|
||
|
// 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();
|
||
|
|
||
|
void PurgeAllMegaTextures();
|
||
|
|
||
|
// 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
|
||
|
virtual 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();
|
||
|
|
||
|
void SetInsideLevelLoad( bool value ) { insideLevelLoad = value; }
|
||
|
|
||
|
void LevelStart();
|
||
|
|
||
|
// During level load, there is the requirement to load textures at two points. Once
|
||
|
// after the level loading GUI has been loaded, and once in EndLevelLoad.
|
||
|
int LoadPendingImages( bool updatePacifier = true );
|
||
|
|
||
|
// used to clear and then write the dds conversion batch file
|
||
|
void StartBuild();
|
||
|
void FinishBuild();
|
||
|
void AddDDSCommand( const char* sourceFile, const char* destFile, const char* codec, const char* params );
|
||
|
|
||
|
virtual void LoadImage( const char* fileName, byte **pic, int *width, int *height, unsigned *timestamp, bool makePowerOf2 );
|
||
|
|
||
|
virtual void FreeImageBuffer( byte*& buffer );
|
||
|
|
||
|
// data is RGB or RGBA
|
||
|
virtual void WriteTGA( const char* fileName, const byte* data, int width, int height, int depth = 4, bool swapBGR = true, bool flipVertical = false );
|
||
|
virtual int WriteTGABuffer( byte*& outBuffer, const byte* data, int width, int height, int depth = 4, bool swapBGR = true, bool flipVertical = false );
|
||
|
|
||
|
// data is RGB or RGBA
|
||
|
virtual void WriteBMP( const char* fileName, const byte* data, int width, int height, int depth = 4 );
|
||
|
virtual int WriteBMPBuffer( byte*& outBuffer, const byte* data, int width, int height, int depth = 4 );
|
||
|
|
||
|
|
||
|
// data is an 8 bit index into palette, which is RGB (no A)
|
||
|
virtual void WritePalTGA( const char *filename, const byte *data, const byte *palette, int width, int height, bool flipVertical = false );
|
||
|
|
||
|
void GetPureServerChecksum( unsigned int& checksum );
|
||
|
|
||
|
// 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_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
|
||
|
#ifdef ID_ALLOW_TOOLS
|
||
|
static idCVar image_usePrecompressedTextures; // use .dds files if present
|
||
|
static idCVar image_writePrecompressedTextures; // write .dds files if necessary
|
||
|
#endif
|
||
|
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_skipUpload; // used during the build process, will skip uploads
|
||
|
static idCVar image_useBackgroundLoads; // 1 = enable background loading of images
|
||
|
static idCVar image_showBackgroundLoads; // 1 = print number of outstanding background loads
|
||
|
static idCVar image_ignoreHighQuality; // ignore high quality on materials
|
||
|
static idCVar image_detailPower; // controls how fast the detail textures fade out
|
||
|
static idCVar image_picMipEnable; // Controls texture miplevel downscale
|
||
|
static idCVar image_picMip; // Controls texture miplevel downscale
|
||
|
static idCVar image_editorPicMip; // Controls texture miplevel downscale
|
||
|
#if !defined( SD_PUBLIC_BUILD )
|
||
|
static idCVar image_globalPicMip; // Controls texture miplevel downscale
|
||
|
#endif // !SD_PUBLIC_BUILD
|
||
|
static idCVar image_bumpPicMip; // Controls texture miplevel downscale
|
||
|
static idCVar image_diffusePicMip; // Controls texture miplevel downscale
|
||
|
static idCVar image_specularPicMip; // Controls texture miplevel downscale
|
||
|
|
||
|
// built-in images
|
||
|
idImage * defaultImage;
|
||
|
idImage * defaultMaterialImage;
|
||
|
idImage * flatNormalMap; // 128 128 255 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 * grayImage; // full of 0x77
|
||
|
idImage * blackImage; // full of 0x00
|
||
|
idImage * normalCubeMapImage; // cube map to normalize STR into RGB
|
||
|
idImage * blackCubeMapImage; // just all black
|
||
|
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 * cinematicYImage;
|
||
|
idImage * cinematicUImage;
|
||
|
idImage * cinematicVImage;
|
||
|
idImage * scratchImage;
|
||
|
idImage * currentRenderImage; // for SS_POST_PROCESS shaders
|
||
|
idImage * currentDepthImage;
|
||
|
idImage * postProcessBuffer[2];
|
||
|
#if 0
|
||
|
GLuint postProcessBufferFBO[2];
|
||
|
#endif
|
||
|
idImage * scratchCubeMapImage;
|
||
|
idImage * scratchImage2; // PENTA: TEST
|
||
|
idImage * noise; // 32x32x32x8bit noise image
|
||
|
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 * dither[16];
|
||
|
idImage * defaultDetailMaskImage;
|
||
|
idImage * diffusionMask;
|
||
|
|
||
|
//--------------------------------------------------------
|
||
|
|
||
|
virtual idImage * AllocImage( const char *name );
|
||
|
void SetNormalPalette();
|
||
|
void ChangeTextureFilter();
|
||
|
|
||
|
idList<idImage*> images;
|
||
|
idStrList ddsSourceFileList;
|
||
|
idStrList ddsDestFileList;
|
||
|
idStrList ddsCodecList;
|
||
|
idStrList ddsParamList;
|
||
|
idHashIndex ddsHash;
|
||
|
|
||
|
idList<idMegaTexture*> megaTextures;
|
||
|
|
||
|
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
|
||
|
|
||
|
int numActiveBackgroundImageLoads;
|
||
|
static const int MAX_BACKGROUND_IMAGE_LOADS = 8;
|
||
|
};
|
||
|
|
||
|
extern idImageManager *globalImages; // pointer to global list for the rest of the system
|
||
|
|
||
|
/*
|
||
|
====================================================================
|
||
|
|
||
|
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], byte amount );
|
||
|
void R_BlendOverTexture( byte *data, int pixelCount, const byte blend[4], byte amount[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 );
|
||
|
void R_SetAlphaChannel( byte *data, int pixelCount, byte alpha );
|
||
|
void R_MakeVirtualTexture( const char *out, int tileSize, int pad, byte *data, int w, int h, bool preserveBorder );
|
||
|
|
||
|
/*
|
||
|
====================================================================
|
||
|
|
||
|
IMAGEFILES
|
||
|
|
||
|
====================================================================
|
||
|
*/
|
||
|
|
||
|
void LoadBMP( const char *name, byte **pic, int *width, int *height, unsigned *timestamp, bool markPaksReferenced = true );
|
||
|
void LoadTGA( const char *name, byte **pic, int *width, int *height, unsigned *timestamp, bool markPaksReferenced = true );
|
||
|
|
||
|
void R_LoadImage( const char *name, byte **pic, int *width, int *height, unsigned *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, unsigned *timestamp );
|
||
|
|
||
|
/*
|
||
|
====================================================================
|
||
|
|
||
|
IMAGEPROGRAM
|
||
|
|
||
|
====================================================================
|
||
|
*/
|
||
|
|
||
|
void R_LoadImageProgram( const char *name, byte **pic, int *width, int *height, unsigned *timestamp, textureDepth_t *depth = NULL );
|
||
|
const char *R_ParsePastImageProgram( idParser &src );
|
||
|
|
||
|
typedef struct {
|
||
|
float percent;
|
||
|
idStr name;
|
||
|
idVec4 color;
|
||
|
} imageClassUsage_t;
|
||
|
|
||
|
float R_GetImageUsageData( idList< imageClassUsage_t > &target );
|
||
|
|
||
|
/*
|
||
|
==============
|
||
|
sdImageSequence
|
||
|
==============
|
||
|
*/
|
||
|
class sdImageSequence {
|
||
|
|
||
|
idList<idImage*> images;
|
||
|
float rate;
|
||
|
|
||
|
public:
|
||
|
|
||
|
sdImageSequence();
|
||
|
~sdImageSequence();
|
||
|
|
||
|
void Cleanup( void );
|
||
|
|
||
|
void SetRate( float r );
|
||
|
void AddImage( idImage *img );
|
||
|
|
||
|
void UpdateBindings( void );
|
||
|
};
|
||
|
|
||
|
#endif /* !__IMAGE_H__ */
|