You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
547 lines
22 KiB
547 lines
22 KiB
//========= 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. |
|
}; |
|
|
|
//=============================================================================== |
|
|
|
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; |
|
}; |
|
|
|
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 ); |
|
|
|
void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true ); |
|
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 |
|
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
|
|
|