//========= Copyright Valve Corporation, All rights reserved. ============//
// TOGL CODE LICENSE
//
// Copyright 2011-2014 Valve Corporation
// All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// cglmtex.h
// GLMgr textures
//
//===============================================================================
# ifndef CGLMTEX_H
# define CGLMTEX_H
# pragma once
# ifdef OSX
# include "glmgrbasics.h"
# endif
# include "tier1/utlhash.h"
# include "tier1/utlmap.h"
//===============================================================================
// forward declarations
class GLMContext ;
class GLMTester ;
class CGLMTexLayoutTable ;
class CGLMTex ;
class CGLMFBO ;
struct IDirect3DSurface9 ;
# if GLMDEBUG
extern CGLMTex * g_pFirstCGMLTex ;
# endif
// For GL_EXT_texture_sRGB_decode
# ifndef GL_TEXTURE_SRGB_DECODE_EXT
# define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
# endif
# ifndef GL_DECODE_EXT
# define GL_DECODE_EXT 0x8A49
# endif
# ifndef GL_SKIP_DECODE_EXT
# define GL_SKIP_DECODE_EXT 0x8A4A
# endif
//===============================================================================
struct GLMTexFormatDesc
{
const char * m_formatSummary ; // for debug visibility
D3DFORMAT m_d3dFormat ; // what D3D knows it as; see public/bitmap/imageformat.h
GLenum m_glIntFormat ; // GL internal format
GLenum m_glIntFormatSRGB ; // internal format if SRGB flavor
GLenum m_glDataFormat ; // GL data format
GLenum m_glDataType ; // GL data type
int m_chunkSize ; // 1 or 4 - 4 is used for compressed textures
int m_bytesPerSquareChunk ; // how many bytes for the smallest quantum (m_chunkSize x m_chunkSize)
// this description lets us calculate size cleanly without conditional logic for compression
} ;
const GLMTexFormatDesc * GetFormatDesc ( D3DFORMAT format ) ;
//===============================================================================
// utility function for generating slabs of texels. mostly for test.
typedef struct
{
// in
D3DFORMAT m_format ;
void * m_dest ; // dest address
int m_chunkCount ; // square chunk count (single texels or compressed blocks)
int m_byteCountLimit ; // caller expectation of max number of bytes to write out
float r , g , b , a ; // color desired
// out
int m_bytesWritten ;
} GLMGenTexelParams ;
// return true if successful
bool GLMGenTexels ( GLMGenTexelParams * params ) ;
//===============================================================================
struct GLMTexLayoutSlice
{
int m_xSize , m_ySize , m_zSize ; //texel dimensions of this slice
int m_storageOffset ; //where in the storage slab does this slice live
int m_storageSize ; //how much storage does this slice occupy
} ;
enum EGLMTexFlags
{
kGLMTexMipped = 0x01 ,
kGLMTexMippedAuto = 0x02 ,
kGLMTexRenderable = 0x04 ,
kGLMTexIsStencil = 0x08 ,
kGLMTexIsDepth = 0x10 ,
kGLMTexSRGB = 0x20 ,
kGLMTexMultisampled = 0x40 , // has an RBO backing it. Cannot combine with Mipped, MippedAuto. One slice maximum, only targeting GL_TEXTURE_2D.
// actually not 100% positive on the mipmapping, the RBO itself can't be mipped, but the resulting texture could
// have mipmaps generated.
kGLMTexDynamic = 0x80
} ;
//===============================================================================
struct GLMTexLayoutKey
{
// input values: held const, these are the hash key for the form map
GLenum m_texGLTarget ; // flavor of texture: GL_TEXTURE_2D, GL_TEXTURE_3D, GLTEXTURE_CUBE_MAP
D3DFORMAT m_texFormat ; // D3D texel format
unsigned long m_texFlags ; // mipped, autogen mips, render target, ... ?
unsigned long m_texSamples ; // zero for a plain tex, 2/4/6/8 for "MSAA tex" (RBO backed)
int m_xSize , m_ySize , m_zSize ; // size of base mip
} ;
bool LessFunc_GLMTexLayoutKey ( const GLMTexLayoutKey & a , const GLMTexLayoutKey & b ) ;
# define GLM_TEX_MAX_MIPS 14
# define GLM_TEX_MAX_FACES 6
# define GLM_TEX_MAX_SLICES (GLM_TEX_MAX_MIPS * GLM_TEX_MAX_FACES)
# pragma warning( push )
# pragma warning( disable : 4200 )
struct GLMTexLayout
{
char * m_layoutSummary ; // for debug visibility
// const inputs used for hashing
GLMTexLayoutKey m_key ;
// refcount
int m_refCount ;
// derived values:
GLMTexFormatDesc * m_format ; // format specific info
int m_mipCount ; // derived by starying at base size and working down towards 1x1
int m_faceCount ; // 1 for 2d/3d, 6 for cubemap
int m_sliceCount ; // product of faces and mips
int m_storageTotalSize ; // size of storage slab required
// slice array
GLMTexLayoutSlice m_slices [ 0 ] ; // dynamically allocated 2-d array [faces][mips]
} ;
# pragma warning( pop )
class CGLMTexLayoutTable
{
public :
CGLMTexLayoutTable ( ) ;
GLMTexLayout * NewLayoutRef ( GLMTexLayoutKey * pDesiredKey ) ; // pass in a pointer to layout key - receive ptr to completed layout
void DelLayoutRef ( GLMTexLayout * layout ) ; // pass in pointer to completed layout. refcount is dropped.
void DumpStats ( void ) ;
protected :
CUtlMap < GLMTexLayoutKey , GLMTexLayout * > m_layoutMap ;
} ;
//===============================================================================
// a sampler specifies desired state for drawing on a given sampler index
// this is the combination of a texture choice and a set of sampler parameters
// see http://msdn.microsoft.com/en-us/library/bb172602(VS.85).aspx
struct GLMTexLockParams
{
// input params which identify the slice of interest
CGLMTex * m_tex ;
int m_face ;
int m_mip ;
// identifies the region of the slice
GLMRegion m_region ;
// tells GLM to force re-read of the texels back from GL
// i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale"
bool m_readback ;
bool m_readonly ;
} ;
struct GLMTexLockDesc
{
GLMTexLockParams m_req ; // form of the lock request
bool m_active ; // set true at lock time. cleared at unlock time.
int m_sliceIndex ; // which slice in the layout
int m_sliceBaseOffset ; // where is that in the texture data
int m_sliceRegionOffset ; // offset to the start (lowest address corner) of the region requested
} ;
//===============================================================================
# define GLM_SAMPLER_COUNT 16
# define GLM_MAX_PIXEL_TEX_SAMPLERS 16
# define GLM_MAX_VERTEX_TEX_SAMPLERS 0
typedef CBitVec < GLM_SAMPLER_COUNT > CTexBindMask ;
enum EGLMTexSliceFlag
{
kSliceValid = 0x01 , // slice has been teximage'd in whole at least once - set to 0 initially
kSliceStorageValid = 0x02 , // if backing store is available, this slice's data is a valid copy - set to 0 initially
kSliceLocked = 0x04 , // are one or more locks outstanding on this slice
kSliceFullyDirty = 0x08 , // does the slice need to be fully downloaded at unlock time (disregard dirty rects)
} ;
//===============================================================================
# define GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS (2)
# define GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS (2)
# define GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS (2)
# define GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS (2)
# define GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS (4)
# define GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS (5)
# define GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS (1)
# define GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS (1)
struct GLMTexPackedSamplingParams
{
uint32 m_addressU : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS ;
uint32 m_addressV : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS ;
uint32 m_addressW : GLM_PACKED_SAMPLER_PARAMS_ADDRESS_BITS ;
uint32 m_minFilter : GLM_PACKED_SAMPLER_PARAMS_MIN_FILTER_BITS ;
uint32 m_magFilter : GLM_PACKED_SAMPLER_PARAMS_MAG_FILTER_BITS ;
uint32 m_mipFilter : GLM_PACKED_SAMPLER_PARAMS_MIP_FILTER_BITS ;
uint32 m_minLOD : GLM_PACKED_SAMPLER_PARAMS_MIN_LOD_BITS ;
uint32 m_maxAniso : GLM_PACKED_SAMPLER_PARAMS_MAX_ANISO_BITS ;
uint32 m_compareMode : GLM_PACKED_SAMPLER_PARAMS_COMPARE_MODE_BITS ;
uint32 m_srgb : GLM_PACKED_SAMPLER_PARAMS_SRGB_BITS ;
uint32 m_isValid : 1 ;
} ;
struct GLMTexSamplingParams
{
union
{
GLMTexPackedSamplingParams m_packed ;
uint32 m_bits ;
} ;
uint32 m_borderColor ;
float m_lodBias ;
FORCEINLINE bool operator = = ( const GLMTexSamplingParams & rhs ) const
{
return ( m_bits = = rhs . m_bits ) & & ( m_borderColor = = rhs . m_borderColor ) & & ( m_lodBias = = rhs . m_lodBias ) ;
}
FORCEINLINE void SetToDefaults ( )
{
m_bits = 0 ;
m_borderColor = 0 ;
m_lodBias = 0.0f ;
m_packed . m_addressU = D3DTADDRESS_WRAP ;
m_packed . m_addressV = D3DTADDRESS_WRAP ;
m_packed . m_addressW = D3DTADDRESS_WRAP ;
m_packed . m_minFilter = D3DTEXF_POINT ;
m_packed . m_magFilter = D3DTEXF_POINT ;
m_packed . m_mipFilter = D3DTEXF_NONE ;
m_packed . m_maxAniso = 1 ;
m_packed . m_compareMode = 0 ;
m_packed . m_isValid = true ;
}
# ifndef OSX
FORCEINLINE void SetToSamplerObject ( GLuint nSamplerObject ) const
{
static const GLenum dxtogl_addressMode [ ] = { GL_REPEAT , GL_CLAMP_TO_EDGE , GL_CLAMP_TO_BORDER , ( GLenum ) - 1 } ;
static const GLenum dxtogl_magFilter [ 4 ] = { GL_NEAREST , GL_NEAREST , GL_LINEAR , GL_LINEAR } ;
static const GLenum dxtogl_minFilter [ 4 ] [ 4 ] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter].
{
/* min = D3DTEXF_NONE */ { GL_NEAREST , GL_NEAREST_MIPMAP_NEAREST , GL_NEAREST_MIPMAP_LINEAR , ( GLenum ) - 1 } , // D3DTEXF_NONE we just treat like POINT
/* min = D3DTEXF_POINT */ { GL_NEAREST , GL_NEAREST_MIPMAP_NEAREST , GL_NEAREST_MIPMAP_LINEAR , ( GLenum ) - 1 } ,
/* min = D3DTEXF_LINEAR */ { GL_LINEAR , GL_LINEAR_MIPMAP_NEAREST , GL_LINEAR_MIPMAP_LINEAR , ( GLenum ) - 1 } ,
/* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR , GL_LINEAR_MIPMAP_NEAREST , GL_LINEAR_MIPMAP_LINEAR , ( GLenum ) - 1 } , // no diff from prior row, set maxAniso to effect the sampling
} ;
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_WRAP_S , dxtogl_addressMode [ m_packed . m_addressU ] ) ;
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_WRAP_T , dxtogl_addressMode [ m_packed . m_addressV ] ) ;
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_WRAP_R , dxtogl_addressMode [ m_packed . m_addressW ] ) ;
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_MIN_FILTER , dxtogl_minFilter [ m_packed . m_minFilter ] [ m_packed . m_mipFilter ] ) ;
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_MAG_FILTER , dxtogl_magFilter [ m_packed . m_magFilter ] ) ;
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_MAX_ANISOTROPY_EXT , m_packed . m_maxAniso ) ;
float flBorderColor [ 4 ] = { 0 , 0 , 0 , 0 } ;
if ( m_borderColor )
{
flBorderColor [ 0 ] = ( ( m_borderColor > > 16 ) & 0xFF ) * ( 1.0f / 255.0f ) ; //R
flBorderColor [ 1 ] = ( ( m_borderColor > > 8 ) & 0xFF ) * ( 1.0f / 255.0f ) ; //G
flBorderColor [ 2 ] = ( ( m_borderColor ) & 0xFF ) * ( 1.0f / 255.0f ) ; //B
flBorderColor [ 3 ] = ( ( m_borderColor > > 24 ) & 0xFF ) * ( 1.0f / 255.0f ) ; //A
}
gGL - > glSamplerParameterfv ( nSamplerObject , GL_TEXTURE_BORDER_COLOR , flBorderColor ) ; // <-- this crashes ATI's driver, remark it out
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_MIN_LOD , m_packed . m_minLOD ) ;
gGL - > glSamplerParameterfv ( nSamplerObject , GL_TEXTURE_LOD_BIAS , & m_lodBias ) ;
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_COMPARE_MODE_ARB , m_packed . m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ) ;
gGL - > glSamplerParameterf ( nSamplerObject , GL_TEXTURE_LOD_BIAS , m_lodBias ) ;
if ( m_packed . m_compareMode )
{
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_COMPARE_FUNC_ARB , GL_LEQUAL ) ;
}
if ( gGL - > m_bHave_GL_EXT_texture_sRGB_decode )
{
gGL - > glSamplerParameteri ( nSamplerObject , GL_TEXTURE_SRGB_DECODE_EXT , m_packed . m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ) ;
}
}
# endif // !OSX
inline void DeltaSetToTarget ( GLenum target , const GLMTexSamplingParams & curState )
{
static const GLenum dxtogl_addressMode [ ] = { GL_REPEAT , GL_CLAMP_TO_EDGE , GL_CLAMP_TO_BORDER , ( GLenum ) - 1 } ;
static const GLenum dxtogl_magFilter [ 4 ] = { GL_NEAREST , GL_NEAREST , GL_LINEAR , GL_LINEAR } ;
static const GLenum dxtogl_minFilter [ 4 ] [ 4 ] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter].
{
/* min = D3DTEXF_NONE */ { GL_NEAREST , GL_NEAREST_MIPMAP_NEAREST , GL_NEAREST_MIPMAP_LINEAR , ( GLenum ) - 1 } , // D3DTEXF_NONE we just treat like POINT
/* min = D3DTEXF_POINT */ { GL_NEAREST , GL_NEAREST_MIPMAP_NEAREST , GL_NEAREST_MIPMAP_LINEAR , ( GLenum ) - 1 } ,
/* min = D3DTEXF_LINEAR */ { GL_LINEAR , GL_LINEAR_MIPMAP_NEAREST , GL_LINEAR_MIPMAP_LINEAR , ( GLenum ) - 1 } ,
/* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR , GL_LINEAR_MIPMAP_NEAREST , GL_LINEAR_MIPMAP_LINEAR , ( GLenum ) - 1 } , // no diff from prior row, set maxAniso to effect the sampling
} ;
if ( m_packed . m_addressU ! = curState . m_packed . m_addressU )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_WRAP_S , dxtogl_addressMode [ m_packed . m_addressU ] ) ;
}
if ( m_packed . m_addressV ! = curState . m_packed . m_addressV )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_WRAP_T , dxtogl_addressMode [ m_packed . m_addressV ] ) ;
}
if ( m_packed . m_addressW ! = curState . m_packed . m_addressW )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_WRAP_R , dxtogl_addressMode [ m_packed . m_addressW ] ) ;
}
if ( ( m_packed . m_minFilter ! = curState . m_packed . m_minFilter ) | |
( m_packed . m_magFilter ! = curState . m_packed . m_magFilter ) | |
( m_packed . m_mipFilter ! = curState . m_packed . m_mipFilter ) | |
( m_packed . m_maxAniso ! = curState . m_packed . m_maxAniso ) )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_MIN_FILTER , dxtogl_minFilter [ m_packed . m_minFilter ] [ m_packed . m_mipFilter ] ) ;
gGL - > glTexParameteri ( target , GL_TEXTURE_MAG_FILTER , dxtogl_magFilter [ m_packed . m_magFilter ] ) ;
gGL - > glTexParameteri ( target , GL_TEXTURE_MAX_ANISOTROPY_EXT , m_packed . m_maxAniso ) ;
}
if ( m_borderColor ! = curState . m_borderColor )
{
float flBorderColor [ 4 ] = { 0 , 0 , 0 , 0 } ;
if ( m_borderColor )
{
flBorderColor [ 0 ] = ( ( m_borderColor > > 16 ) & 0xFF ) * ( 1.0f / 255.0f ) ; //R
flBorderColor [ 1 ] = ( ( m_borderColor > > 8 ) & 0xFF ) * ( 1.0f / 255.0f ) ; //G
flBorderColor [ 2 ] = ( ( m_borderColor ) & 0xFF ) * ( 1.0f / 255.0f ) ; //B
flBorderColor [ 3 ] = ( ( m_borderColor > > 24 ) & 0xFF ) * ( 1.0f / 255.0f ) ; //A
}
gGL - > glTexParameterfv ( target , GL_TEXTURE_BORDER_COLOR , flBorderColor ) ; // <-- this crashes ATI's driver, remark it out
}
if ( m_packed . m_minLOD ! = curState . m_packed . m_minLOD )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_MIN_LOD , m_packed . m_minLOD ) ;
}
if ( m_lodBias ! = curState . m_lodBias )
{
// Could use TexParameterf instead, but we don't currently grab it. This works fine, too.
gGL - > glTexParameterfv ( target , GL_TEXTURE_LOD_BIAS , & m_lodBias ) ;
}
if ( m_packed . m_compareMode ! = curState . m_packed . m_compareMode )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_COMPARE_MODE_ARB , m_packed . m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ) ;
if ( m_packed . m_compareMode )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_COMPARE_FUNC_ARB , GL_LEQUAL ) ;
}
}
if ( ( gGL - > m_bHave_GL_EXT_texture_sRGB_decode ) & & ( m_packed . m_srgb ! = curState . m_packed . m_srgb ) )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_SRGB_DECODE_EXT , m_packed . m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ) ;
}
}
inline void SetToTarget ( GLenum target )
{
static const GLenum dxtogl_addressMode [ ] = { GL_REPEAT , GL_CLAMP_TO_EDGE , GL_CLAMP_TO_BORDER , ( GLenum ) - 1 } ;
static const GLenum dxtogl_magFilter [ 4 ] = { GL_NEAREST , GL_NEAREST , GL_LINEAR , GL_LINEAR } ;
static const GLenum dxtogl_minFilter [ 4 ] [ 4 ] = // indexed by _D3DTEXTUREFILTERTYPE on both axes: [row is min filter][col is mip filter].
{
/* min = D3DTEXF_NONE */ { GL_NEAREST , GL_NEAREST_MIPMAP_NEAREST , GL_NEAREST_MIPMAP_LINEAR , ( GLenum ) - 1 } , // D3DTEXF_NONE we just treat like POINT
/* min = D3DTEXF_POINT */ { GL_NEAREST , GL_NEAREST_MIPMAP_NEAREST , GL_NEAREST_MIPMAP_LINEAR , ( GLenum ) - 1 } ,
/* min = D3DTEXF_LINEAR */ { GL_LINEAR , GL_LINEAR_MIPMAP_NEAREST , GL_LINEAR_MIPMAP_LINEAR , ( GLenum ) - 1 } ,
/* min = D3DTEXF_ANISOTROPIC */ { GL_LINEAR , GL_LINEAR_MIPMAP_NEAREST , GL_LINEAR_MIPMAP_LINEAR , ( GLenum ) - 1 } , // no diff from prior row, set maxAniso to effect the sampling
} ;
gGL - > glTexParameteri ( target , GL_TEXTURE_WRAP_S , dxtogl_addressMode [ m_packed . m_addressU ] ) ;
gGL - > glTexParameteri ( target , GL_TEXTURE_WRAP_T , dxtogl_addressMode [ m_packed . m_addressV ] ) ;
gGL - > glTexParameteri ( target , GL_TEXTURE_WRAP_R , dxtogl_addressMode [ m_packed . m_addressW ] ) ;
gGL - > glTexParameteri ( target , GL_TEXTURE_MIN_FILTER , dxtogl_minFilter [ m_packed . m_minFilter ] [ m_packed . m_mipFilter ] ) ;
gGL - > glTexParameteri ( target , GL_TEXTURE_MAG_FILTER , dxtogl_magFilter [ m_packed . m_magFilter ] ) ;
gGL - > glTexParameteri ( target , GL_TEXTURE_MAX_ANISOTROPY_EXT , m_packed . m_maxAniso ) ;
float flBorderColor [ 4 ] = { 0 , 0 , 0 , 0 } ;
if ( m_borderColor )
{
flBorderColor [ 0 ] = ( ( m_borderColor > > 16 ) & 0xFF ) * ( 1.0f / 255.0f ) ; //R
flBorderColor [ 1 ] = ( ( m_borderColor > > 8 ) & 0xFF ) * ( 1.0f / 255.0f ) ; //G
flBorderColor [ 2 ] = ( ( m_borderColor ) & 0xFF ) * ( 1.0f / 255.0f ) ; //B
flBorderColor [ 3 ] = ( ( m_borderColor > > 24 ) & 0xFF ) * ( 1.0f / 255.0f ) ; //A
}
gGL - > glTexParameterfv ( target , GL_TEXTURE_BORDER_COLOR , flBorderColor ) ; // <-- this crashes ATI's driver, remark it out
gGL - > glTexParameteri ( target , GL_TEXTURE_MIN_LOD , m_packed . m_minLOD ) ;
gGL - > glTexParameterfv ( target , GL_TEXTURE_LOD_BIAS , & m_lodBias ) ;
gGL - > glTexParameteri ( target , GL_TEXTURE_COMPARE_MODE_ARB , m_packed . m_compareMode ? GL_COMPARE_R_TO_TEXTURE_ARB : GL_NONE ) ;
if ( m_packed . m_compareMode )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_COMPARE_FUNC_ARB , GL_LEQUAL ) ;
}
if ( gGL - > m_bHave_GL_EXT_texture_sRGB_decode )
{
gGL - > glTexParameteri ( target , GL_TEXTURE_SRGB_DECODE_EXT , m_packed . m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ) ;
}
}
} ;
//===============================================================================
class CGLMTex
{
public :
void Lock ( GLMTexLockParams * params , char * * addressOut , int * yStrideOut , int * zStrideOut ) ;
void Unlock ( GLMTexLockParams * params ) ;
GLuint GetTexName ( ) { return m_texName ; }
protected :
friend class GLMContext ; // only GLMContext can make CGLMTex objects
friend class GLMTester ;
friend class CGLMFBO ;
friend struct IDirect3DDevice9 ;
friend struct IDirect3DBaseTexture9 ;
friend struct IDirect3DTexture9 ;
friend struct IDirect3DSurface9 ;
friend struct IDirect3DCubeTexture9 ;
friend struct IDirect3DVolumeTexture9 ;
CGLMTex ( GLMContext * ctx , GLMTexLayout * layout , uint levels , const char * debugLabel = NULL ) ;
~ CGLMTex ( ) ;
int CalcSliceIndex ( int face , int mip ) ;
void CalcTexelDataOffsetAndStrides ( int sliceIndex , int x , int y , int z , int * offsetOut , int * yStrideOut , int * zStrideOut ) ;
GLubyte * ReadTexels ( GLMTexLockDesc * desc , bool readWholeSlice = true , bool readOnly = false ) ;
void WriteTexels ( GLMTexLockDesc * desc , bool writeWholeSlice = true , bool noDataWrite = false ) ;
// last param lets us send NULL data ptr (only legal with uncompressed formats, beware)
// this helps out ResetSRGB.
# if defined( OSX )
void HandleSRGBMismatch ( bool srgb , int & srgbFlipCount ) ;
void ResetSRGB ( bool srgb , bool noDataWrite ) ;
// re-specify texture format to match desired sRGB form
// noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's
# endif
bool IsRBODirty ( ) const ;
void ForceRBONonDirty ( ) ;
void ForceRBODirty ( ) ;
// re-specify texture format to match desired sRGB form
// noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's
GLuint m_texName ; // name of this texture in the context
GLuint m_pbo ;
GLubyte * m_mapped ;
GLenum m_texGLTarget ;
uint m_nSamplerType ; // SAMPLER_2D, etc.
GLMTexSamplingParams m_SamplingParams ;
GLMTexLayout * m_layout ; // layout of texture (shared across all tex with same layout)
uint m_nLastResolvedBatchCounter ;
int m_minActiveMip ; //index of lowest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL.
int m_maxActiveMip ; //index of highest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL.
GLMContext * m_ctx ; // link back to parent context
CGLMFBO * m_pBlitSrcFBO ;
CGLMFBO * m_pBlitDstFBO ;
GLuint m_rboName ; // name of MSAA RBO backing the tex if MSAA enabled (or zero)
int m_rtAttachCount ; // how many RT's have this texture attached somewhere
char * m_backing ; // backing storage if available
int m_lockCount ; // lock reqs are stored in the GLMContext for tracking
CUtlVector < unsigned char > m_sliceFlags ;
char * m_debugLabel ; // strdup() of debugLabel passed in, or NULL
bool m_texClientStorage ; // was CS selected for texture
bool m_texPreloaded ; // has it been kicked into VRAM with GLMContext::PreloadTex yet
int m_srgbFlipCount ;
# if GLMDEBUG
CGLMTex * m_pPrevTex ;
CGLMTex * m_pNextTex ;
# endif
} ;
# endif