This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

99
public/glmgr/cglmbuffer.h Normal file
View File

@@ -0,0 +1,99 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// cglmprogram.h
// GLMgr buffers (index / vertex)
// ... maybe add PBO later as well
//===============================================================================
#ifndef CGLMBUFFER_H
#define CGLMBUFFER_H
#pragma once
// ext links
// http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
//===============================================================================
// tokens not in the SDK headers
//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT
// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9
//#endif
//===============================================================================
// forward declarations
class GLMContext;
enum EGLMBufferType
{
kGLMVertexBuffer,
kGLMIndexBuffer,
kGLMUniformBuffer, // for bindable uniform
kGLMPixelBuffer, // for PBO
kGLMNumBufferTypes
};
// pass this in "options" to constructor to make a dynamic buffer
#define GLMBufferOptionDynamic 0x00000001
struct GLMBuffLockParams
{
uint m_offset;
uint m_size;
bool m_nonblocking;
bool m_discard;
};
class CGLMBuffer
{
public:
void Lock( GLMBuffLockParams *params, char **addressOut );
void Unlock( void );
//protected:
friend class GLMContext; // only GLMContext can make CGLMBuffer objects
friend class GLMTester;
friend class IDirect3D9;
friend class IDirect3DDevice9;
CGLMBuffer ( GLMContext *ctx, EGLMBufferType type, uint size, uint options );
~CGLMBuffer ( );
void SetModes ( bool asyncMap, bool explicitFlush, bool force = false );
void FlushRange ( uint offset, uint size );
GLMContext *m_ctx; // link back to parent context
EGLMBufferType m_type;
uint m_size;
GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB
GLuint m_name; // name of this program in the context
uint m_revision; // bump anytime the size changes or buffer is orphaned
bool m_enableAsyncMap; // mirror of the buffer state
bool m_enableExplicitFlush; // mirror of the buffer state
bool m_bound; // true if bound to context
bool m_mapped; // is it currently mapped
uint m_dirtyMinOffset; // when equal, range is empty
uint m_dirtyMaxOffset;
float *m_lastMappedAddress;
// --------------------- pseudo-VBO support below here (explicitly for dynamic index buffers)
bool m_pseudo; // true if the m_name is 0, and the backing is plain RAM
// in pseudo mode, there is just one RAM buffer that acts as the backing.
// expectation is that this mode would only be used for dynamic indices.
// since indices have to be consumed (copied to command stream) prior to return from a drawing call,
// there's no need to do any fencing or multibuffering. orphaning in particular becomes a no-op.
char *m_pseudoBuf; // storage for pseudo buffer
};
#endif

91
public/glmgr/cglmfbo.h Normal file
View File

@@ -0,0 +1,91 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// cglmfbo.h
// GLMgr FBO's (render targets)
//
//===============================================================================
#ifndef CGLMFBO_H
#define CGLMFBO_H
#pragma once
#include "glmgr/cglmtex.h"
// good FBO references / recaps
// http://www.songho.ca/opengl/gl_fbo.html
// http://www.gamedev.net/reference/articles/article2331.asp
// ext links
// http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
// http://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt
//===============================================================================
// tokens not in the SDK headers
#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT
#define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9
#endif
//===============================================================================
// forward declarations
class GLMContext;
// implicitly 16 maximum color attachments possible
enum EGLMFBOAttachment {
kAttColor0, kAttColor1, kAttColor2, kAttColor3,
kAttColor4, kAttColor5, kAttColor6, kAttColor7,
kAttColor8, kAttColor9, kAttColor10, kAttColor11,
kAttColor12, kAttColor13, kAttColor14, kAttColor15,
kAttDepth, kAttStencil, kAttDepthStencil,
kAttCount
};
struct GLMFBOTexAttachParams
{
CGLMTex *m_tex;
int m_face; // keep zero if not cube map
int m_mip; // keep zero if notmip mapped
int m_zslice; // keep zero if not a 3D tex
};
class CGLMFBO
{
public:
protected:
friend class GLMContext; // only GLMContext can make CGLMFBO objects
friend class GLMTester;
friend class CGLMTex;
friend class IDirect3D9;
friend class IDirect3DDevice9;
CGLMFBO( GLMContext *ctx );
~CGLMFBO( );
void TexAttach( GLMFBOTexAttachParams *params, EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT );
void TexDetach( EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT );
// you can also pass GL_READ_FRAMEBUFFER_EXT or GL_DRAW_FRAMEBUFFER_EXT to selectively bind the receiving FBO to one or the other.
void TexScrub( CGLMTex *tex );
// search and destroy any attachment for the named texture
bool IsReady( void ); // aka FBO completeness check - ready to draw
GLMContext *m_ctx; // link back to parent context
GLuint m_name; // name of this FBO in the context
GLMFBOTexAttachParams m_attach[ kAttCount ]; // indexed by EGLMFBOAttachment
int m_sizeX,m_sizeY;
};
#endif

291
public/glmgr/cglmprogram.h Normal file
View File

@@ -0,0 +1,291 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// cglmprogram.h
// GLMgr programs (ARBVP/ARBfp)
//
//===============================================================================
#ifndef CGLMPROGRAM_H
#define CGLMPROGRAM_H
#include <sys/stat.h>
#pragma once
// good ARB program references
// http://petewarden.com/notes/archives/2005/05/fragment_progra_2.html
// http://petewarden.com/notes/archives/2005/06/fragment_progra_3.html
// ext links
// http://www.opengl.org/registry/specs/ARB/vertex_program.txt
// http://www.opengl.org/registry/specs/ARB/fragment_program.txt
// http://www.opengl.org/registry/specs/EXT/gpu_program_parameters.txt
//===============================================================================
// tokens not in the SDK headers
//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT
// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9
//#endif
//===============================================================================
// forward declarations
class GLMContext;
class CGLMShaderPair;
class CGLMShaderPairCache;
// CGLMProgram can contain two flavors of the same program, one in assembler, one in GLSL.
// these flavors are pretty different in terms of the API's that are used to activate them -
// for example, assembler programs can just get bound to the context, whereas GLSL programs
// have to be linked. To some extent we try to hide that detail inside GLM.
// for now, make CGLMProgram a container, it does not set policy or hold a preference as to which
// flavor you want to use. GLMContext has to handle that.
enum EGLMProgramType
{
kGLMVertexProgram,
kGLMFragmentProgram,
kGLMNumProgramTypes
};
enum EGLMProgramLang
{
kGLMARB,
kGLMGLSL,
kGLMNumProgramLangs
};
struct GLMShaderDesc
{
union
{
GLuint arb; // ARB program object name
GLhandleARB glsl; // GLSL shader object handle (void*)
} m_object;
// these can change if shader text is edited
bool m_textPresent; // is this flavor(lang) of text present in the buffer?
int m_textOffset; // where is it
int m_textLength; // how big
bool m_compiled; // has this text been through a compile attempt
bool m_valid; // and if so, was the compile successful
int m_slowMark; // has it been flagged during a non native draw batch before. increment every time it's slow.
int m_highWater; // vount of vec4's in the major uniform array ("vc" on vs, "pc" on ps)
// written by dxabstract.... gross!
};
GLenum GLMProgTypeToARBEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target
GLenum GLMProgTypeToGLSLEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target
class CGLMProgram
{
public:
friend class CGLMShaderPairCache;
friend class CGLMShaderPair;
friend class GLMContext; // only GLMContext can make CGLMProgram objects
friend class GLMTester;
friend class IDirect3D9;
friend class IDirect3DDevice9;
//===============================
// constructor is very light, it just makes one empty program object per flavor.
CGLMProgram( GLMContext *ctx, EGLMProgramType type );
~CGLMProgram( );
void SetProgramText ( char *text ); // import text to GLM object - invalidate any prev compiled program
bool CompileActiveSources ( void ); // compile only the flavors that were provided.
bool Compile ( EGLMProgramLang lang );
bool CheckValidity ( EGLMProgramLang lang );
void LogSlow ( EGLMProgramLang lang ); // detailed spew when called for first time; one liner or perhaps silence after that
void GetLabelIndexCombo ( char *labelOut, int labelOutMaxChars, int *indexOut, int *comboOut );
void GetComboIndexNameString ( char *stringOut, int stringOutMaxChars ); // mmmmmmmm-nnnnnnnn-filename
#if GLMDEBUG
bool PollForChanges( void ); // check mirror for changes.
void ReloadStringFromEditable( void ); // populate m_string from editable item (react to change)
bool SyncWithEditable( void );
#endif
//===============================
// common stuff
GLMContext *m_ctx; // link back to parent context
EGLMProgramType m_type; // vertex or pixel
uint m_serial; // serial number for hashing
char *m_text; // copy of text passed into constructor. Can change if editable shaders is enabled.
// note - it can contain multiple flavors, so use CGLMTextSectioner to scan it and locate them
#if GLMDEBUG
CGLMEditableTextItem *m_editable; // editable text item for debugging
#endif
GLMShaderDesc m_descs[ kGLMNumProgramLangs ];
uint m_samplerMask; // (1<<n) mask of sampler active locs, if this is a fragment shader (dxabstract sets this field)
};
//===============================================================================
struct GLMShaderPairInfo
{
int m_status; // -1 means req'd index was out of bounds (loop stop..) 0 means not present. 1 means present/active.
char m_vsName[ 128 ];
int m_vsStaticIndex;
int m_vsDynamicIndex;
char m_psName[ 128 ];
int m_psStaticIndex;
int m_psDynamicIndex;
};
class CGLMShaderPair // a container for a linked GLSL shader pair, and metadata obtained post-link
{
public:
friend class CGLMProgram;
friend class GLMContext;
friend class CGLMShaderPairCache;
//===============================
// constructor just sets up a GLSL program object and leaves it empty.
CGLMShaderPair( GLMContext *ctx );
~CGLMShaderPair( );
bool SetProgramPair ( CGLMProgram *vp, CGLMProgram *fp );
// true result means successful link and query
bool RefreshProgramPair ( void );
// re-link and re-query the uniforms
//===============================
// common stuff
GLMContext *m_ctx; // link back to parent context
CGLMProgram *m_vertexProg;
CGLMProgram *m_fragmentProg;
GLhandleARB m_program; // linked program object
// need meta data for attribs / samplers / params
// actually we only need it for samplers and params.
// attributes are hardwired.
// vertex stage uniforms
GLint m_locVertexParams; // "vc" per dx9asmtogl2 convention
GLint m_locVertexInteger0; // "i0"
GLint m_locVertexBool0; // "b0"
GLint m_locVertexBool1; // "b1"
GLint m_locVertexBool2; // "b2"
GLint m_locVertexBool3; // "b3"
// fragment stage uniforms
GLint m_locFragmentParams; // "pc" per dx9asmtogl2 convention
GLint m_locFragmentFakeSRGBEnable; // "flSRGBWrite" - set to 1.0 to effect sRGB encoding on output
float m_fakeSRGBEnableValue; // shadow to avoid redundant sets of the m_locFragmentFakeSRGBEnable uniform
// init it to -1.0 at link or relink, so it will trip on any legit incoming value (0.0 or 1.0)
GLint m_locSamplers[ 16 ]; // "sampler0 ... sampler1..."
// other stuff
bool m_valid; // true on successful link
bool m_samplersFixed; // set on first draw (can't write the uniforms until the program is in use, and we don't want to mess with cur program inside cglmprogram)
uint m_revision; // if this pair is relinked, bump this number.
};
//===============================================================================
// N-row, M-way associative cache with LRU per row.
// still needs some metric dump ability and some parameter tuning.
// extra credit would be to make an auto-tuner.
struct CGLMPairCacheEntry
{
long long m_lastMark; // a mark of zero means an empty entry
CGLMProgram *m_vertexProg;
CGLMProgram *m_fragmentProg;
uint m_extraKeyBits;
CGLMShaderPair *m_pair;
};
class CGLMShaderPairCache // cache for linked GLSL shader pairs
{
public:
protected:
friend class CGLMShaderPair;
friend class CGLMProgram;
friend class GLMContext;
//===============================
CGLMShaderPairCache( GLMContext *ctx );
~CGLMShaderPairCache( );
CGLMShaderPair *SelectShaderPair ( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits );
void QueryShaderPair ( int index, GLMShaderPairInfo *infoOut );
// shoot down linked pairs that use the program in the arg
// return true if any had to be skipped due to conflict with currently bound pair
bool PurgePairsWithShader( CGLMProgram *prog );
// purge everything (when would GLM know how to do this ? at context destroy time, but any other times?)
// return true if any had to be skipped due to conflict with currently bound pair
bool Purge ( void );
// stats
void DumpStats ( void );
//===============================
uint HashRowIndex ( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits );
CGLMPairCacheEntry* HashRowPtr ( uint hashRowIndex );
void HashRowProbe ( CGLMPairCacheEntry *row, CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int *hitwayOut, int *emptywayOut, int *oldestwayOut );
//===============================
// common stuff
GLMContext *m_ctx; // link back to parent context
long long m_mark;
uint m_rowsLg2;
uint m_rows;
uint m_waysLg2;
uint m_ways;
uint m_entryCount;
CGLMPairCacheEntry *m_entries; // array[ m_rows ][ m_ways ]
uint *m_evictions; // array[ m_rows ];
uint *m_hits; // array[ m_rows ];
};
#endif

84
public/glmgr/cglmquery.h Normal file
View File

@@ -0,0 +1,84 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// cglmquery.h
// GLMgr queries
//
//===============================================================================
#ifndef CGLMQUERY_H
#define CGLMQUERY_H
#pragma once
#ifdef OSX
#include "glmgr/glmgrbasics.h"
#endif
//===============================================================================
// forward declarations
class GLMContext;
class CGLMQuery;
//===============================================================================
enum EGLMQueryType
{
EOcclusion,
EFence,
EGLMQueryCount
};
struct GLMQueryParams
{
EGLMQueryType m_type;
};
class CGLMQuery
{
// leave everything public til it's running
public:
friend class GLMContext; // only GLMContext can make CGLMTex objects
friend class IDirect3DDevice9;
friend class IDirect3DQuery9;
GLMContext *m_ctx; // link back to parent context
GLMQueryParams m_params; // params created with
GLuint m_name; // name of the query object per se - could be fence, could be query object
bool m_started;
bool m_stopped;
bool m_done;
bool m_nullQuery; // was gl_nullqueries true at Start time - if so, continue to act like a null query through Stop/IsDone/Complete time
// restated - only Start should examine the convar.
CGLMQuery( GLMContext *ctx, GLMQueryParams *params );
~CGLMQuery( );
// for an occlusion query:
// Start = BeginQuery query-start goes into stream
// Stop = EndQuery query-end goes into stream - a fence is also set so we can probe for completion
// IsDone = TestFence use the added fence to ask if query-end has passed (i.e. will Complete block?)
// Complete = GetQueryObjectuivARB(uint id, enum pname, uint *params) - extract the sample count
// for a fence query:
// Start = SetFence fence goes into command stream
// Stop = NOP fences are self finishing - no need to call Stop on a fence
// IsDone = TestFence ask if fence passed
// Complete = FinishFence
void Start ( void );
void Stop ( void );
bool IsDone ( void );
void Complete ( uint *result );
// accessors for the started/stopped state
bool IsStarted ( void );
bool IsStopped ( void );
};
#endif

277
public/glmgr/cglmtex.h Normal file
View File

@@ -0,0 +1,277 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// cglmtex.h
// GLMgr textures
//
//===============================================================================
#ifndef CGLMTEX_H
#define CGLMTEX_H
#pragma once
#ifdef OSX
#include "glmgr/glmgrbasics.h"
#endif
#include "tier1/utlhash.h"
#include "tier1/utlmap.h"
//===============================================================================
// forward declarations
class GLMContext;
class GLMTester;
class CGLMTexLayoutTable;
class CGLMTex;
class CGLMFBO;
class IDirect3DSurface9;
//===============================================================================
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,
kGLMTexUnused = 0x40, // UNUSED
kGLMTexMultisampled = 0x80, // 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)
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]
};
class CGLMTexLayoutTable
{
public:
CGLMTexLayoutTable();
GLMTexLayout *NewLayoutRef( GLMTexLayoutKey *key ); // 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 GLMTexSamplingParams
{
GLenum m_addressModes[3]; // S, T, R
GLfloat m_borderColor[4]; // R,G,B,A
GLenum m_magFilter;
GLenum m_minFilter;
GLfloat m_mipmapBias;
GLint m_minMipLevel;
GLint m_maxMipLevel;
GLint m_maxAniso;
GLenum m_compareMode; // only used for depth and stencil type textures
bool m_srgb; // srgb texture read...
};
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
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)
};
class CGLMTex
{
public:
void Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut, int *zStrideOut );
void Unlock( GLMTexLockParams *params );
protected:
friend class GLMContext; // only GLMContext can make CGLMTex objects
friend class GLMTester;
friend class CGLMFBO;
friend class IDirect3DDevice9;
friend class IDirect3DBaseTexture9;
friend class IDirect3DTexture9;
friend class IDirect3DSurface9;
friend class IDirect3DCubeTexture9;
friend class IDirect3DVolumeTexture9;
CGLMTex( GLMContext *ctx, GLMTexLayout *layout, GLMTexSamplingParams *sampling, 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 ApplySamplingParams( GLMTexSamplingParams *params, bool noCheck=FALSE );
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.
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
GLMTexLayout *m_layout; // layout of texture (shared across all tex with same layout)
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.
GLMTexSamplingParams m_sampling; // mirror of sampling params currently embodied in the texture
// (consult this at draw time, in order to know if changes need to be made)
GLMContext *m_ctx; // link back to parent context
GLuint m_texName; // name of this texture in the context
bool m_texClientStorage; // was CS selecetd for texture
bool m_texPreloaded; // has it been kicked into VRAM with GLMContext::PreloadTex yet
GLuint m_rboName; // name of MSAA RBO backing the tex if MSAA enabled (or zero)
bool m_rboDirty; // has RBO been drawn on - i.e. needs to be blitted back to texture if texture is going to be sampled from
CTexBindMask m_bindPoints; // true for each place in the parent ctx where currently
// bound (indexed via EGLMTexCtxBindingIndex)
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
};
#endif

45
public/glmgr/glmdebug.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef GLMDEBUG_H
#define GLMDEBUG_H
// include this anywhere you need to be able to compile-out code related specifically to GLM debugging.
// we expect DEBUG to be driven by the build system so you can include this header anywhere.
// when we come out, GLMDEBUG will be defined to a value - 0, 1, or 2
// 0 means no GLM debugging is possible
// 1 means it's possible and resulted from being a debug build
// 2 means it's possible and resulted from being manually forced on for a release build
#if defined( POSIX ) && !defined( _PS3 )
#ifndef GLMDEBUG
#ifdef DEBUG
#define GLMDEBUG 1 // normally 1 here, testing
#else
// #define GLMDEBUG 2 // don't check this in enabled..
#endif
#ifndef GLMDEBUG
#define GLMDEBUG 0
#endif
#endif
#else
#ifndef GLMDEBUG
#define GLMDEBUG 0
#endif
#endif
// helpful macro if you are in a position to call GLM functions directly (i.e. you live in materialsystem / shaderapidx9)
#if GLMDEBUG
#define GLMPRINTF(args) GLMPrintf args
#define GLMPRINTSTR(args) GLMPrintStr args
#define GLMPRINTTEXT(args) GLMPrintText args
#define GLMBEGINPIXEVENT(args) GLMBeginPIXEvent args
#define GLMENDPIXEVENT(args) GLMEndPIXEvent args
#else
#define GLMPRINTF(args)
#define GLMPRINTSTR(args)
#define GLMPRINTTEXT(args)
#define GLMBEGINPIXEVENT(args)
#define GLMENDPIXEVENT(args)
#endif
#endif

165
public/glmgr/glmdisplay.h Normal file
View File

@@ -0,0 +1,165 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// glmdisplay.h
// display related stuff - used by both GLMgr and the CocoaMgr
//
//===============================================================================
#ifndef GLMDISPLAY_H
#define GLMDISPLAY_H
#pragma once
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#include <OpenGL/CGLTypes.h>
#include <OpenGL/CGLRenderers.h>
#include <OpenGL/CGLCurrent.h>
#include <ApplicationServices/ApplicationServices.h>
typedef void _PseudoNSGLContext; // aka NSOpenGLContext
typedef _PseudoNSGLContext *PseudoNSGLContextPtr;
struct GLMDisplayModeInfoFields
{
uint m_modePixelWidth;
uint m_modePixelHeight;
uint m_modeRefreshHz;
// are we even going to talk about bit depth... not yet
};
struct GLMDisplayInfoFields
{
CGDirectDisplayID m_cgDisplayID;
CGOpenGLDisplayMask m_glDisplayMask; // result of CGDisplayIDToOpenGLDisplayMask on the cg_displayID.
uint m_displayPixelWidth;
uint m_displayPixelHeight;
};
struct GLMRendererInfoFields
{
/*properties of interest and their desired values.
kCGLRPFullScreen = 54, true
kCGLRPAccelerated = 73, true
kCGLRPWindow = 80, true
kCGLRPRendererID = 70, informational
kCGLRPDisplayMask = 84, informational
kCGLRPBufferModes = 100, informational
kCGLRPColorModes = 103, informational
kCGLRPAccumModes = 104, informational
kCGLRPDepthModes = 105, informational
kCGLRPStencilModes = 106, informational
kCGLRPMaxAuxBuffers = 107, informational
kCGLRPMaxSampleBuffers = 108, informational
kCGLRPMaxSamples = 109, informational
kCGLRPSampleModes = 110, informational
kCGLRPSampleAlpha = 111, informational
kCGLRPVideoMemory = 120, informational
kCGLRPTextureMemory = 121, informational
kCGLRPRendererCount = 128 number of renderers in the CGLRendererInfoObj under examination
kCGLRPOffScreen = 53, D/C
kCGLRPRobust = 75, FALSE or D/C - aka we're asking for no-fallback
kCGLRPBackingStore = 76, D/C
kCGLRPMPSafe = 78, D/C
kCGLRPMultiScreen = 81, D/C
kCGLRPCompliant = 83, D/C
*/
//--------------------------- info we have from CGL renderer queries, IOKit, Gestalt
//--------------------------- these are set up in the displayDB by CocoaMgr
GLint m_fullscreen;
GLint m_accelerated;
GLint m_windowed;
GLint m_rendererID;
GLint m_displayMask;
GLint m_bufferModes;
GLint m_colorModes;
GLint m_accumModes;
GLint m_depthModes;
GLint m_stencilModes;
GLint m_maxAuxBuffers;
GLint m_maxSampleBuffers;
GLint m_maxSamples;
GLint m_sampleModes;
GLint m_sampleAlpha;
GLint m_vidMemory;
GLint m_texMemory;
uint m_pciVendorID;
uint m_pciDeviceID;
char m_pciModelString[64];
char m_driverInfoString[64];
//--------------------------- OS version related - set up by CocoaMgr
// OS version found
uint m_osComboVersion; // 0x00XXYYZZ : XX major, YY minor, ZZ minor minor : 10.6.3 --> 0x000A0603. 10.5.8 --> 0x000A0508.
//--------------------------- shorthands - also set up by CocoaMgr - driven by vendorid / deviceid
bool m_ati;
bool m_atiR5xx;
bool m_atiR6xx;
bool m_atiR7xx;
bool m_atiR8xx;
bool m_atiNewer;
bool m_intel;
bool m_intel95x;
bool m_intel3100;
bool m_intelNewer;
bool m_nv;
bool m_nvG7x;
bool m_nvG8x;
bool m_nvNewer;
//--------------------------- context query results - left blank in the display DB - but valid in a GLMContext (call ctx->Caps() to get a const ref)
// booleans
bool m_hasGammaWrites; // aka glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT) / glEnable(GL_FRAMEBUFFER_SRGB_EXT)
bool m_hasSRGBDecode; // Support for GL_EXT_texture_sRGB_decode, which came in with 10.6.7
bool m_hasMixedAttachmentSizes; // aka ARB_fbo in 10.6.3 - test for min OS vers, then exported ext string
bool m_hasBGRA; // aka GL_BGRA vertex attribs in 10.6.3 - - test for min OS vers, then exported ext string
bool m_hasNewFullscreenMode; // aka 10.6.x "big window" fullscreen mode
bool m_hasNativeClipVertexMode; // aka GLSL gl_ClipVertex does not fall back to SW- OS version and folklore-based
bool m_hasOcclusionQuery; // occlusion query: do you speak it ?!
bool m_hasFramebufferBlit; // framebuffer blit: know what I'm sayin?!
bool m_hasPerfPackage1; // means new MTGL, fast OQ, fast uniform upload, NV can resolve flipped (late summer 2010 post 10.6.4 update)
// counts
int m_maxAniso; // aniso limit - context query
// other exts
bool m_hasBindableUniforms;
bool m_hasUniformBuffers;
// runtime options that aren't negotiable once set
bool m_hasDualShaders; // must supply CLI arg "-glmdualshaders" or we go GLSL only
//--------------------------- " can'ts " - specific problems that need to be worked around
bool m_cantBlitReliably; // Intel chipsets have problems blitting sRGB sometimes
bool m_cantAttachSRGB; // NV G8x on 10.5.8 can't have srgb tex on FBO color - separate issue from hasGammaWrites
bool m_cantResolveFlipped; // happens on NV in 10.6.4 and prior - console variable "gl_can_resolve_flipped" can overrule
bool m_cantResolveScaled; // happens everywhere per GL spec but may be relaxed some day - console variable "gl_can_resolve_scaled" can overrule
bool m_costlyGammaFlips; // this means that sRGB sampling state affects shader code gen, resulting in state-dependent code regen
//--------------------------- " bads " - known bad drivers
bool m_badDriver1064NV; // this is the bad NVIDIA driver on 10.6.4 - stutter, tex corruption, black screen issues
};
#endif

1028
public/glmgr/glmgr.h Normal file

File diff suppressed because it is too large Load Diff

384
public/glmgr/glmgrbasics.h Normal file
View File

@@ -0,0 +1,384 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// glmgrbasics.h
// types, common headers, forward declarations, utilities
//
//===============================================================================
#ifndef GLMBASICS_H
#define GLMBASICS_H
#pragma once
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#include <OpenGL/CGLTypes.h>
#include <OpenGL/CGLRenderers.h>
#include <OpenGL/CGLCurrent.h>
#include <OpenGL/CGLProfiler.h>
#include <ApplicationServices/ApplicationServices.h>
#include "bitmap/imageformat.h"
#include "bitvec.h"
#include "tier1/checksum_md5.h"
#include "tier1/utlvector.h"
#include "tier1/convar.h"
#include <sys/stat.h>
#include "glmgr/glmdebug.h"
// types
// 3-d integer box (used for texture lock/unlock etc)
struct GLMRegion
{
int xmin,xmax;
int ymin,ymax;
int zmin,zmax;
};
struct GLMRect // follows GL convention - if coming from the D3D rect you will need to fiddle the Y's
{
int xmin; // left
int ymin; // bottom
int xmax; // right
int ymax; // top
};
// macros
//#define GLMassert(x) assert(x)
// forward decls
class GLMgr; // singleton
class GLMContext; // GL context
class CGLMContextTester; // testing class
class CGLMTex;
class CGLMFBO;
class CGLMProgram;
class CGLMBuffer;
// utilities
typedef enum
{
// D3D codes
eD3D_DEVTYPE,
eD3D_FORMAT,
eD3D_RTYPE,
eD3D_USAGE,
eD3D_RSTATE, // render state
eD3D_SIO, // D3D shader bytecode
eD3D_VTXDECLUSAGE,
// CGL codes
eCGL_RENDID,
// OpenGL error codes
eGL_ERROR,
// OpenGL enums
eGL_ENUM,
eGL_RENDERER
} GLMThing_t;
const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const
const char* GLMDecodeMask( GLMThing_t type, unsigned long value ); // decode a bitmask
void GLMStop( void ); // aka Debugger()
void GLMCheckError( bool noStop = false, bool noLog= false );
void GLMEnableTrace( bool on );
//===============================================================================
// debug channels
enum EGLMDebugChannel
{
ePrintf,
eDebugger,
eGLProfiler
};
#if GLMDEBUG
// make all these prototypes disappear in non GLMDEBUG
void GLMDebugInitialize( bool forceReinit=false );
bool GLMDetectOGLP( void );
bool GLMDetectGDB( void );
uint GLMDetectAvailableChannels( void );
uint GLMDebugChannelMask( uint *newValue = NULL );
// note that GDB and OGLP can both come and go during run - forceCheck will allow that to be detected.
// mask returned is in form of 1<<n, n from EGLMDebugChannel
#endif
//===============================================================================
// debug message flavors
enum EGLMDebugFlavor
{
eAllFlavors, // 0
eDebugDump, // 1 debug dump flavor -D-
eTenure, // 2 code tenures > <
eComment, // 3 one off messages ---
eMatrixData, // 4 matrix data -M-
eShaderData, // 5 shader data (params) -S-
eFrameBufData, // 6 FBO data (attachments) -F-
eDXStuff, // 7 dxabstract spew -X-
eAllocations, // 8 tracking allocs and frees -A-
eSlowness, // 9 slow things happening (srgb flips..) -Z-
eDefaultFlavor, // not specified (no marker)
eFlavorCount
};
uint GLMDebugFlavorMask( uint *newValue = NULL );
//===============================================================================
// output functions
// make all these prototypes disappear in non GLMDEBUG
#if GLMDEBUG
// these are unconditional outputs, they don't interrogate the string
void GLMStringOut( const char *string );
void GLMStringOutIndented( const char *string, int indentColumns );
// these will look at the string to guess its flavor: <, >, ---, -M-, -S-
void GLMPrintfVA( const char *fmt, va_list vargs );
void GLMPrintf( const char *fmt, ... );
// these take an explicit flavor with a default value
void GLMPrintStr( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor );
#define GLMPRINTTEXT_NUMBEREDLINES 0x80000000
void GLMPrintText( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor, uint options=0 ); // indent each newline
int GLMIncIndent( int indentDelta );
int GLMGetIndent( void );
void GLMSetIndent( int indent );
#endif
// expose these in release now
// Mimic PIX events so we can decorate debug spew
void GLMBeginPIXEvent( const char *str );
void GLMEndPIXEvent( void );
//===============================================================================
// knob twiddling
float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value
float GLMKnobToggle( char *knobname );
//===============================================================================
// other stuff
#if GLMDEBUG
inline void GLMDebugger( void )
{
if (GLMDebugChannelMask() & (1<<eDebugger))
{
asm ( "int $3" );
}
if (GLMDebugChannelMask() & (1<<eGLProfiler))
{
// we call an obscure GL function which we know has been breakpointed in the OGLP function list
static short nada[] = {0xFFFF,0xFFFF,0xFFFF,0xFFFF};
glColor4sv( nada );
}
}
#else
#define GLMDebugger()
#endif
// helpers for CGLSetOption - no op if no profiler
void GLMProfilerClearTrace( void );
void GLMProfilerEnableTrace( bool enable );
// helpers for CGLSetParameter - no op if no profiler
void GLMProfilerDumpState( void );
//===============================================================================
// classes
// helper class making function tracking easier to wire up
#if GLMDEBUG || GLMDEBUG_PS3
//extern bool g_bEnableGLMDebug;
class GLMFuncLogger
{
public:
// simple function log
GLMFuncLogger( const char *funcName )
{
m_funcName = funcName;
m_earlyOut = false;
// if ( g_bEnableGLMDebug )
// {
// GLMPrintf( ">%s\n", m_funcName );
// }
};
// more advanced version lets you pass args (i.e. called parameters or anything else of interest)
// no macro for this one, since no easy way to pass through the args as well as the funcname
GLMFuncLogger( const char *funcName, char *fmt, ... )
{
m_funcName = funcName;
m_earlyOut = false;
// this acts like GLMPrintf here
// all the indent policy is down in GLMPrintfVA
// which means we need to inject a ">" at the front of the format string to make this work... sigh.
char modifiedFmt[2000];
modifiedFmt[0] = '>';
strcpy( modifiedFmt+1, fmt );
va_list vargs;
va_start(vargs, fmt);
GLMPrintfVA( modifiedFmt, vargs );
va_end( vargs );
}
~GLMFuncLogger( )
{
return;
// if ( !g_bEnableGLMDebug )
// return;
if (m_earlyOut)
{
GLMPrintf( "<%s (early out)", m_funcName );
}
else
{
GLMPrintf( "<%s", m_funcName );
}
};
void EarlyOut( void )
{
m_earlyOut = true;
};
const char *m_funcName; // set at construction time
bool m_earlyOut;
};
// handy macro to go with the function tracking class
#define GLM_FUNC GLMFuncLogger _logger_ ( __FUNCTION__ )
#else
#define GLM_FUNC
#endif
// class to keep an in-memory mirror of a file which may be getting edited during run
class CGLMFileMirror
{
public:
CGLMFileMirror( char *fullpath ); // just associates mirror with file. if file exists it will be read.
//if non existent it will be created with size zero
~CGLMFileMirror( );
bool HasData( void ); // see if data avail
void GetData( char **dataPtr, uint *dataSizePtr ); // read it out
void SetData( char *data, uint dataSize ); // put data in (and write it to disk)
bool PollForChanges( void ); // check disk copy. If different, read it back in and return true.
void UpdateStatInfo( void ); // make sure stat info is current for our file
void ReadFile( void );
void WriteFile( void );
void OpenInEditor( bool foreground=false ); // pass TRUE if you would like the editor to pop to foreground
/// how about a "wait for change" method..
char *m_path; // fullpath to file
bool m_exists;
struct stat m_stat; // stat results for the file (last time checked)
char *m_data; // content of file
uint m_size; // length of content
};
// class based on the file mirror, that makes it easy to edit them outside the app.
// it receives an initial block of text from the engine, and hashes it. ("orig")
// it munges it by duplicating all the text after the "!!" line, and appending it in commented form. ("munged")
// a mirror file is activated, using a filename based on the hash from the orig text.
// if there is already content on disk matching that filename, use that content *unless* the 'blitz' parameter is set.
// (i.e. engine is instructing this subsystem to wipe out any old/modified variants of the text)
class CGLMEditableTextItem
{
public:
CGLMEditableTextItem( char *text, uint size, bool forceOverwrite, char *prefix, char *suffix = NULL ); // create a text blob from text source, optional filename suffix
~CGLMEditableTextItem( );
bool HasData( void );
bool PollForChanges( void ); // return true if stale i.e. you need to get a new edition
void GetCurrentText( char **textOut, uint *sizeOut ); // query for read access to the active blob (could be the original, could be external edited copy)
void OpenInEditor( bool foreground=false ); // call user attention to this text
// internal methods
void GenHashOfOrigText( void );
void GenBaseNameAndFullPath( char *prefix, char *suffix );
void GenMungedText( bool fromMirror );
// members
// orig
uint m_origSize;
char *m_origText; // what was submitted
unsigned char m_origDigest[MD5_DIGEST_LENGTH]; // digest of what was submitted
// munged
uint m_mungedSize;
char *m_mungedText; // re-processed edition, initial content submission to the file mirror
// mirror
char *m_mirrorBaseName; // generated from the hash of the orig text, plus the label / prefix
char *m_mirrorFullPath; // base name
CGLMFileMirror *m_mirror; // file mirror itself. holds "official" copy for GetCurrentText to return.
};
// debug font
extern unsigned char g_glmDebugFontMap[16384];
// class for cracking multi-part text blobs
// sections are demarcated by beginning-of-line markers submitted in a table by the caller
struct GLMTextSection
{
int m_markerIndex; // based on table of markers passed in to constructor
uint m_textOffset; // where is the text - offset
int m_textLength; // how big is the section
};
class CGLMTextSectioner
{
public:
CGLMTextSectioner( char *text, int textSize, const char **markers ); // constructor finds all the sections
~CGLMTextSectioner( );
int Count( void ); // how many sections found
void GetSection( int index, uint *offsetOut, uint *lengthOut, int *markerIndexOut );
// find section, size, what marker
// note that more than one section can be marked similarly.
// so policy isn't made here, you walk the sections and decide what to do if there are dupes.
//members
//section table
CUtlVector< GLMTextSection > m_sectionTable;
};
#endif

102
public/glmgr/glmgrext.h Normal file
View File

@@ -0,0 +1,102 @@
//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// glmgrext.h
// helper file for extension testing and runtime importing of entry points
//
//===============================================================================
#pragma once
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
// #define symbol INSTANTIATE_GL_IMPORTS controls whether the following macro "GL_IMPORT" writes externs or writes decls
// normally only glmgr.cpp sets that symbol and includes this file
// to simplify usage, a function ptr type must exist for every entry point, following the name##FuncPtr convention.
#ifdef INSTANTIATE_GL_IMPORTS
#define GL_IMPORT( name ) name##FuncPtr name = 0
#else
#define GL_IMPORT( name ) extern name##FuncPtr name;
#endif
// before declaring each import, check to see if the EXT symbol is in effect,
// and if so, don't do it!
#ifndef GL_EXT_draw_buffers2
typedef void (* glColorMaskIndexedEXTFuncPtr) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
typedef void (* glEnableIndexedEXTFuncPtr) (GLenum target, GLuint index);
typedef void (* glDisableIndexedEXTFuncPtr) (GLenum target, GLuint index);
GL_IMPORT(glColorMaskIndexedEXT);
GL_IMPORT(glEnableIndexedEXT);
GL_IMPORT(glDisableIndexedEXT);
#endif
#ifndef GL_EXT_framebuffer_sRGB
#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
#endif
#ifndef ARB_texture_rg
#define GL_COMPRESSED_RED 0x8225
#define GL_COMPRESSED_RG 0x8226
#define GL_RG 0x8227
#define GL_RG_INTEGER 0x8228
#define GL_R8 0x8229
#define GL_R16 0x822A
#define GL_RG8 0x822B
#define GL_RG16 0x822C
#define GL_R16F 0x822D
#define GL_R32F 0x822E
#define GL_RG16F 0x822F
#define GL_RG32F 0x8230
#define GL_R8I 0x8231
#define GL_R8UI 0x8232
#define GL_R16I 0x8233
#define GL_R16UI 0x8234
#define GL_R32I 0x8235
#define GL_R32UI 0x8236
#define GL_RG8I 0x8237
#define GL_RG8UI 0x8238
#define GL_RG16I 0x8239
#define GL_RG16UI 0x823A
#define GL_RG32I 0x823B
#define GL_RG32UI 0x823C
#define GL_RGB10_A2UI_ARB 0x906F
#endif
#ifndef GL_EXT_bindable_uniform
#define GL_UNIFORM_BUFFER_EXT 0x8DEE
#endif
// unpublished extension enums (thus the "X")
// from EXT_framebuffer_multisample_blit_scaled..
#define XGL_SCALED_RESOLVE_FASTEST_EXT 0x90BA
#define XGL_SCALED_RESOLVE_NICEST_EXT 0x90BB
void * NSGLGetProcAddress (const char *name);
// call this to find all the entry points.
void GLMSetupExtensions( void );
typedef void (*PFNglColorMaskIndexedEXT)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
typedef void (*PFNglEnableIndexedEXT)(GLenum target, GLuint index);
typedef void (*PFNglDisableIndexedEXT)(GLenum target, GLuint index);
typedef void (*PFNglUniformBufferEXT)(GLuint program, GLint location, GLuint buffer);
extern PFNglColorMaskIndexedEXT pfnglColorMaskIndexedEXT;
extern PFNglEnableIndexedEXT pfnglEnableIndexedEXT;
extern PFNglDisableIndexedEXT pfnglDisableIndexedEXT;
extern PFNglUniformBufferEXT pfnglUniformBufferEXT;
typedef void (*PFNglGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
extern PFNglGetFramebufferAttachmentParameteriv pfnglGetFramebufferAttachmentParameteriv;