Copy original togl to track changes
This commit is contained in:
parent
d947e5e20e
commit
76bfcf40ca
2
public/togles/glfuncs.inl
Normal file
2
public/togles/glfuncs.inl
Normal file
@ -0,0 +1,2 @@
|
||||
#include "togl/linuxwin/glfuncs.h"
|
||||
|
262
public/togles/linuxwin/cglmbuffer.h
Normal file
262
public/togles/linuxwin/cglmbuffer.h
Normal file
@ -0,0 +1,262 @@
|
||||
//========= 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.
|
||||
//
|
||||
// cglmprogram.h
|
||||
// GLMgr buffers (index / vertex)
|
||||
// ... maybe add PBO later as well
|
||||
//===============================================================================
|
||||
|
||||
#ifndef CGLMBUFFER_H
|
||||
#define CGLMBUFFER_H
|
||||
|
||||
#pragma once
|
||||
|
||||
//===============================================================================
|
||||
|
||||
extern bool g_bUsePseudoBufs;
|
||||
|
||||
// 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_nOffset;
|
||||
uint m_nSize;
|
||||
bool m_bNoOverwrite;
|
||||
bool m_bDiscard;
|
||||
};
|
||||
|
||||
#define GL_STATIC_BUFFER_SIZE ( 2048 * 1024 )
|
||||
#define GL_MAX_STATIC_BUFFERS 2
|
||||
|
||||
extern void glBufferSubDataMaxSize( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data, uint nMaxSizePerCall = 128 * 1024 );
|
||||
|
||||
//===========================================================================//
|
||||
|
||||
// Creates an immutable storage for a buffer object
|
||||
// https://www.opengl.org/registry/specs/ARB/buffer_storage.txt
|
||||
class CPersistentBuffer
|
||||
{
|
||||
public:
|
||||
|
||||
CPersistentBuffer();
|
||||
~CPersistentBuffer();
|
||||
|
||||
void Init( EGLMBufferType type,uint nSize );
|
||||
void Deinit();
|
||||
|
||||
void InsertFence();
|
||||
void BlockUntilNotBusy();
|
||||
|
||||
void Append( uint nSize );
|
||||
|
||||
inline uint GetBytesRemaining() const { return m_nSize - m_nOffset; }
|
||||
inline uint GetOffset() const { return m_nOffset; }
|
||||
inline void *GetPtr() const { return m_pImmutablePersistentBuf; }
|
||||
inline GLuint GetHandle() const { return m_nHandle; }
|
||||
|
||||
private:
|
||||
|
||||
CPersistentBuffer( const CPersistentBuffer & );
|
||||
CPersistentBuffer & operator= (const CPersistentBuffer &);
|
||||
|
||||
uint m_nSize;
|
||||
|
||||
EGLMBufferType m_type;
|
||||
GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB
|
||||
GLuint m_nHandle; // handle of this program in the GL context
|
||||
|
||||
// Holds a pointer to the persistently mapped buffer
|
||||
void* m_pImmutablePersistentBuf;
|
||||
|
||||
uint m_nOffset;
|
||||
|
||||
#ifdef HAVE_GL_ARB_SYNC
|
||||
GLsync m_nSyncObj;
|
||||
#endif
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
#if GL_ENABLE_INDEX_VERIFICATION
|
||||
|
||||
struct GLDynamicBuf_t
|
||||
{
|
||||
GLenum m_nGLType;
|
||||
uint m_nHandle;
|
||||
uint m_nActualBufSize;
|
||||
uint m_nSize;
|
||||
|
||||
uint m_nLockOffset;
|
||||
uint m_nLockSize;
|
||||
};
|
||||
|
||||
class CGLMBufferSpanManager
|
||||
{
|
||||
CGLMBufferSpanManager( const CGLMBufferSpanManager& );
|
||||
CGLMBufferSpanManager& operator= ( const CGLMBufferSpanManager& );
|
||||
|
||||
public:
|
||||
CGLMBufferSpanManager();
|
||||
~CGLMBufferSpanManager();
|
||||
|
||||
void Init( GLMContext *pContext, EGLMBufferType nBufType, uint nInitialCapacity, uint nBufSize, bool bDynamic );
|
||||
void Deinit();
|
||||
|
||||
inline GLMContext *GetContext() const { return m_pCtx; }
|
||||
|
||||
inline GLenum GetGLBufType() const { return ( m_nBufType == kGLMVertexBuffer ) ? GL_ARRAY_BUFFER_ARB : GL_ELEMENT_ARRAY_BUFFER_ARB; }
|
||||
|
||||
struct ActiveSpan_t
|
||||
{
|
||||
uint m_nStart;
|
||||
uint m_nEnd;
|
||||
|
||||
GLDynamicBuf_t m_buf;
|
||||
bool m_bOriginalAlloc;
|
||||
|
||||
inline ActiveSpan_t() { }
|
||||
inline ActiveSpan_t( uint nStart, uint nEnd, GLDynamicBuf_t &buf, bool bOriginalAlloc ) : m_nStart( nStart ), m_nEnd( nEnd ), m_buf( buf ), m_bOriginalAlloc( bOriginalAlloc ) { Assert( nStart <= nEnd ); }
|
||||
};
|
||||
|
||||
ActiveSpan_t *AddSpan( uint nOffset, uint nMaxSize, uint nActualSize, bool bDiscard, bool bNoOverwrite );
|
||||
|
||||
void DiscardAllSpans();
|
||||
|
||||
bool IsValid( uint nOffset, uint nSize ) const;
|
||||
|
||||
private:
|
||||
bool AllocDynamicBuf( uint nSize, GLDynamicBuf_t &buf );
|
||||
void ReleaseDynamicBuf( GLDynamicBuf_t &buf );
|
||||
|
||||
GLMContext *m_pCtx;
|
||||
|
||||
EGLMBufferType m_nBufType;
|
||||
|
||||
uint m_nBufSize;
|
||||
bool m_bDynamic;
|
||||
|
||||
CUtlVector<ActiveSpan_t> m_ActiveSpans;
|
||||
CUtlVector<ActiveSpan_t> m_DeletedSpans;
|
||||
|
||||
int m_nSpanEndMax;
|
||||
|
||||
int m_nNumAllocatedBufs;
|
||||
int m_nTotalBytesAllocated;
|
||||
};
|
||||
|
||||
#endif // GL_ENABLE_INDEX_VERIFICATION
|
||||
|
||||
class CGLMBuffer
|
||||
{
|
||||
public:
|
||||
void Lock( GLMBuffLockParams *pParams, char **pAddressOut );
|
||||
void Unlock( int nActualSize = -1, const void *pActualData = NULL );
|
||||
|
||||
GLuint GetHandle() const;
|
||||
|
||||
friend class GLMContext; // only GLMContext can make CGLMBuffer objects
|
||||
friend class GLMTester;
|
||||
friend struct IDirect3D9;
|
||||
friend struct IDirect3DDevice9;
|
||||
|
||||
CGLMBuffer( GLMContext *pCtx, EGLMBufferType type, uint size, uint options );
|
||||
~CGLMBuffer();
|
||||
|
||||
void SetModes( bool bAsyncMap, bool bExplicitFlush, bool bForce = false );
|
||||
void FlushRange( uint offset, uint size );
|
||||
|
||||
#if GL_ENABLE_INDEX_VERIFICATION
|
||||
bool IsSpanValid( uint nOffset, uint nSize ) const;
|
||||
#endif
|
||||
|
||||
GLMContext *m_pCtx; // link back to parent context
|
||||
EGLMBufferType m_type;
|
||||
uint m_nSize;
|
||||
uint m_nActualSize;
|
||||
|
||||
bool m_bDynamic;
|
||||
|
||||
GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB
|
||||
GLuint m_nHandle; // name of this program in the context
|
||||
|
||||
uint m_nRevision; // bump anytime the size changes or buffer is orphaned
|
||||
|
||||
bool m_bEnableAsyncMap; // mirror of the buffer state
|
||||
bool m_bEnableExplicitFlush; // mirror of the buffer state
|
||||
|
||||
bool m_bMapped; // is it currently mapped
|
||||
|
||||
uint m_dirtyMinOffset; // when equal, range is empty
|
||||
uint m_dirtyMaxOffset;
|
||||
|
||||
float *m_pLastMappedAddress;
|
||||
|
||||
int m_nPinnedMemoryOfs;
|
||||
|
||||
uint m_nPersistentBufferStartOffset;
|
||||
bool m_bUsingPersistentBuffer;
|
||||
|
||||
bool m_bPseudo; // 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_pActualPseudoBuf; // storage for pseudo buffer
|
||||
char *m_pPseudoBuf; // storage for pseudo buffer
|
||||
char *m_pStaticBuffer;
|
||||
|
||||
GLMBuffLockParams m_LockParams;
|
||||
|
||||
static char ALIGN16 m_StaticBuffers[ GL_MAX_STATIC_BUFFERS ][ GL_STATIC_BUFFER_SIZE ] ALIGN16_POST;
|
||||
static bool m_bStaticBufferUsed[ GL_MAX_STATIC_BUFFERS ];
|
||||
|
||||
#if GL_ENABLE_INDEX_VERIFICATION
|
||||
CGLMBufferSpanManager m_BufferSpanManager;
|
||||
#endif
|
||||
|
||||
#if GL_ENABLE_UNLOCK_BUFFER_OVERWRITE_DETECTION
|
||||
uint m_nDirtyRangeStart;
|
||||
uint m_nDirtyRangeEnd;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // CGLMBUFFER_H
|
||||
|
104
public/togles/linuxwin/cglmfbo.h
Normal file
104
public/togles/linuxwin/cglmfbo.h
Normal file
@ -0,0 +1,104 @@
|
||||
//========= 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.
|
||||
//
|
||||
// cglmfbo.h
|
||||
// GLMgr FBO's (render targets)
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef CGLMFBO_H
|
||||
#define CGLMFBO_H
|
||||
|
||||
#pragma once
|
||||
|
||||
// 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;
|
||||
|
||||
enum EGLMFBOAttachment
|
||||
{
|
||||
kAttColor0, kAttColor1, kAttColor2, kAttColor3,
|
||||
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
|
||||
{
|
||||
friend class GLMContext;
|
||||
friend class GLMTester;
|
||||
friend class CGLMTex;
|
||||
|
||||
friend struct IDirect3D9;
|
||||
friend struct IDirect3DDevice9;
|
||||
|
||||
public:
|
||||
CGLMFBO( GLMContext *ctx );
|
||||
~CGLMFBO( );
|
||||
|
||||
protected:
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
#endif
|
458
public/togles/linuxwin/cglmprogram.h
Normal file
458
public/togles/linuxwin/cglmprogram.h
Normal file
@ -0,0 +1,458 @@
|
||||
//========= 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.
|
||||
//
|
||||
// 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; // count of vec4's in the major uniform array ("vc" on vs, "pc" on ps)
|
||||
// written by dxabstract.... gross!
|
||||
int m_VSHighWaterBone; // count of vec4's in the bone-specific uniform array (only valid for vertex shaders)
|
||||
};
|
||||
|
||||
GLenum GLMProgTypeToARBEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target
|
||||
GLenum GLMProgTypeToGLSLEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target
|
||||
|
||||
#define GL_SHADER_PAIR_CACHE_STATS 0
|
||||
|
||||
class CGLMProgram
|
||||
{
|
||||
public:
|
||||
friend class CGLMShaderPairCache;
|
||||
friend class CGLMShaderPair;
|
||||
friend class GLMContext; // only GLMContext can make CGLMProgram objects
|
||||
friend class GLMTester;
|
||||
friend struct IDirect3D9;
|
||||
friend struct 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
|
||||
void SetShaderName ( const char *name ); // only used for debugging/telemetry markup
|
||||
|
||||
void CompileActiveSources ( void ); // compile only the flavors that were provided.
|
||||
void 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
|
||||
|
||||
unsigned long m_nHashTag; // 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)
|
||||
uint m_samplerTypes; // SAMPLER_2D, etc.
|
||||
uint m_fragDataMask; // (1<<n) mask of gl_FragData[n] outputs referenced, if this is a fragment shader (dxabstract sets this field)
|
||||
uint m_numDrawBuffers; // number of draw buffers used
|
||||
GLenum m_drawBuffers[4]; // GL_COLOR_ATTACHMENT0_EXT1, etc
|
||||
uint m_nNumUsedSamplers;
|
||||
uint m_maxSamplers;
|
||||
uint m_maxVertexAttrs;
|
||||
uint m_nCentroidMask;
|
||||
uint m_nShadowDepthSamplerMask;
|
||||
|
||||
bool m_bTranslatedProgram;
|
||||
|
||||
char m_shaderName[64];
|
||||
|
||||
// Cache label string from the shader text
|
||||
// example:
|
||||
// trans#2871 label:vs-file vertexlit_and_unlit_generic_vs20 vs-index 294912 vs-combo 1234
|
||||
char m_labelName[1024];
|
||||
int m_labelIndex;
|
||||
int m_labelCombo;
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
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
|
||||
// Note that checking the link status and querying the uniform can be optionally
|
||||
// deferred to take advantage of multi-threaded compilation in the driver
|
||||
|
||||
bool RefreshProgramPair ( void );
|
||||
// re-link and re-query the uniforms
|
||||
|
||||
bool ValidateProgramPair( void );
|
||||
// true result means successful link and query
|
||||
|
||||
FORCEINLINE void UpdateScreenUniform( uint nWidthHeight )
|
||||
{
|
||||
if ( m_nScreenWidthHeight == nWidthHeight )
|
||||
return;
|
||||
|
||||
m_nScreenWidthHeight = nWidthHeight;
|
||||
|
||||
float fWidth = (float)( nWidthHeight & 0xFFFF ), fHeight = (float)( nWidthHeight >> 16 );
|
||||
// Apply half pixel offset to output vertices to account for the pixel center difference between D3D9 and OpenGL.
|
||||
// We output vertices in clip space, which ranges from [-1,1], so 1.0/width in clip space transforms into .5/width in screenspace, see: "Viewports and Clipping (Direct3D 9)" in the DXSDK
|
||||
float v[4] = { 1.0f / fWidth, 1.0f / fHeight, fWidth, fHeight };
|
||||
if ( m_locVertexScreenParams >= 0 )
|
||||
gGL->glUniform4fv( m_locVertexScreenParams, 1, v );
|
||||
}
|
||||
|
||||
//===============================
|
||||
|
||||
// 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_locVertexBoneParams; // "vcbones"
|
||||
GLint m_locVertexInteger0; // "i0"
|
||||
|
||||
enum { cMaxVertexShaderBoolUniforms = 4, cMaxFragmentShaderBoolUniforms = 1 };
|
||||
|
||||
GLint m_locVertexBool[cMaxVertexShaderBoolUniforms]; // "b0", etc.
|
||||
GLint m_locFragmentBool[cMaxFragmentShaderBoolUniforms]; // "fb0", etc.
|
||||
bool m_bHasBoolOrIntUniforms;
|
||||
|
||||
// fragment stage uniforms
|
||||
GLint m_locFragmentParams; // "pc" per dx9asmtogl2 convention
|
||||
|
||||
int m_NumUniformBufferParams[kGLMNumProgramTypes];
|
||||
GLint m_UniformBufferParams[kGLMNumProgramTypes][256];
|
||||
|
||||
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[ GLM_SAMPLER_COUNT ]; // "sampler0 ... sampler1..."
|
||||
|
||||
// other stuff
|
||||
bool m_valid; // true on successful link
|
||||
bool m_bCheckLinkStatus;
|
||||
uint m_revision; // if this pair is relinked, bump this number.
|
||||
|
||||
GLint m_locVertexScreenParams; // vcscreen
|
||||
uint m_nScreenWidthHeight;
|
||||
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// 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( );
|
||||
|
||||
FORCEINLINE 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 );
|
||||
|
||||
//===============================
|
||||
|
||||
FORCEINLINE uint HashRowIndex( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ) const;
|
||||
FORCEINLINE CGLMPairCacheEntry* HashRowPtr( uint hashRowIndex ) const;
|
||||
|
||||
FORCEINLINE void HashRowProbe( CGLMPairCacheEntry *row, CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int &hitway, int &emptyway, int &oldestway );
|
||||
|
||||
CGLMShaderPair *SelectShaderPairInternal( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int rowIndex );
|
||||
//===============================
|
||||
|
||||
// common stuff
|
||||
|
||||
GLMContext *m_ctx; // link back to parent context
|
||||
|
||||
long long m_mark;
|
||||
|
||||
uint m_rowsLg2;
|
||||
uint m_rows;
|
||||
uint m_rowsMask;
|
||||
|
||||
uint m_waysLg2;
|
||||
uint m_ways;
|
||||
|
||||
uint m_entryCount;
|
||||
|
||||
CGLMPairCacheEntry *m_entries; // array[ m_rows ][ m_ways ]
|
||||
|
||||
uint *m_evictions; // array[ m_rows ];
|
||||
|
||||
#if GL_SHADER_PAIR_CACHE_STATS
|
||||
uint *m_hits; // array[ m_rows ];
|
||||
#endif
|
||||
};
|
||||
|
||||
FORCEINLINE uint CGLMShaderPairCache::HashRowIndex( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits ) const
|
||||
{
|
||||
return ( vp->m_nHashTag + fp->m_nHashTag + extraKeyBits * 7 ) & m_rowsMask;
|
||||
}
|
||||
|
||||
FORCEINLINE CGLMPairCacheEntry* CGLMShaderPairCache::HashRowPtr( uint hashRowIndex ) const
|
||||
{
|
||||
return &m_entries[ hashRowIndex * m_ways ];
|
||||
}
|
||||
|
||||
FORCEINLINE void CGLMShaderPairCache::HashRowProbe( CGLMPairCacheEntry *row, CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int& hitway, int& emptyway, int& oldestway )
|
||||
{
|
||||
hitway = -1;
|
||||
emptyway = -1;
|
||||
oldestway = -1;
|
||||
|
||||
// scan this row to see if the desired pair is present
|
||||
CGLMPairCacheEntry *cursor = row;
|
||||
long long oldestmark = 0xFFFFFFFFFFFFFFFFLL;
|
||||
|
||||
for( uint way = 0; way < m_ways; ++way )
|
||||
{
|
||||
if ( cursor->m_lastMark != 0 ) // occupied slot
|
||||
{
|
||||
// check if this is the oldest one on the row - only occupied slots are checked
|
||||
if ( cursor->m_lastMark < oldestmark )
|
||||
{
|
||||
oldestway = way;
|
||||
oldestmark = cursor->m_lastMark;
|
||||
}
|
||||
|
||||
if ( ( cursor->m_vertexProg == vp ) && ( cursor->m_fragmentProg == fp ) && ( cursor->m_extraKeyBits == extraKeyBits ) ) // match?
|
||||
{
|
||||
// found it
|
||||
hitway = way;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// empty way, log it if first one seen
|
||||
if (emptyway<0)
|
||||
{
|
||||
emptyway = way;
|
||||
}
|
||||
}
|
||||
cursor++;
|
||||
}
|
||||
}
|
||||
|
||||
FORCEINLINE CGLMShaderPair *CGLMShaderPairCache::SelectShaderPair( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits )
|
||||
{
|
||||
// select row where pair would be found if it exists
|
||||
uint rowIndex = HashRowIndex( vp, fp, extraKeyBits );
|
||||
|
||||
CGLMPairCacheEntry *pCursor = HashRowPtr( rowIndex );
|
||||
|
||||
if ( ( pCursor->m_fragmentProg != fp ) || ( pCursor->m_vertexProg != vp ) || ( pCursor->m_extraKeyBits != extraKeyBits ) )
|
||||
{
|
||||
CGLMPairCacheEntry *pLastCursor = pCursor + m_ways;
|
||||
|
||||
++pCursor;
|
||||
|
||||
while ( pCursor != pLastCursor )
|
||||
{
|
||||
if ( ( pCursor->m_fragmentProg == fp ) && ( pCursor->m_vertexProg == vp ) && ( pCursor->m_extraKeyBits == extraKeyBits ) ) // match?
|
||||
break;
|
||||
++pCursor;
|
||||
};
|
||||
|
||||
if ( pCursor == pLastCursor )
|
||||
return SelectShaderPairInternal( vp, fp, extraKeyBits, rowIndex );
|
||||
}
|
||||
|
||||
// found it. mark it and return
|
||||
pCursor->m_lastMark = m_mark++;
|
||||
|
||||
#if GL_SHADER_PAIR_CACHE_STATS
|
||||
// count the hit
|
||||
m_hits[ rowIndex ] ++;
|
||||
#endif
|
||||
|
||||
return pCursor->m_pair;
|
||||
}
|
||||
|
||||
#endif
|
108
public/togles/linuxwin/cglmquery.h
Normal file
108
public/togles/linuxwin/cglmquery.h
Normal file
@ -0,0 +1,108 @@
|
||||
//========= 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.
|
||||
//
|
||||
// cglmquery.h
|
||||
// GLMgr queries
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef CGLMQUERY_H
|
||||
#define CGLMQUERY_H
|
||||
|
||||
#pragma once
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// 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 struct IDirect3DDevice9;
|
||||
friend struct 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 ... NOT USED WITH GL_ARB_sync!
|
||||
#ifdef HAVE_GL_ARB_SYNC
|
||||
GLsync m_syncobj; // GL_ARB_sync object. NOT USED WITH GL_NV_fence or GL_APPLE_fence!
|
||||
#else
|
||||
GLuint m_syncobj;
|
||||
#endif
|
||||
|
||||
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.
|
||||
static uint s_nTotalOcclusionQueryCreatesOrDeletes;
|
||||
|
||||
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
|
547
public/togles/linuxwin/cglmtex.h
Normal file
547
public/togles/linuxwin/cglmtex.h
Normal file
@ -0,0 +1,547 @@
|
||||
//========= 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
|
1444
public/togles/linuxwin/dxabstract.h
Normal file
1444
public/togles/linuxwin/dxabstract.h
Normal file
File diff suppressed because it is too large
Load Diff
1748
public/togles/linuxwin/dxabstract_types.h
Normal file
1748
public/togles/linuxwin/dxabstract_types.h
Normal file
File diff suppressed because it is too large
Load Diff
117
public/togles/linuxwin/glbase.h
Normal file
117
public/togles/linuxwin/glbase.h
Normal file
@ -0,0 +1,117 @@
|
||||
//========= 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.
|
||||
//
|
||||
// glbase.h
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef GLBASE_H
|
||||
#define GLBASE_H
|
||||
|
||||
#ifdef DX_TO_GL_ABSTRACTION
|
||||
|
||||
#undef HAVE_GL_ARB_SYNC
|
||||
|
||||
#ifndef OSX
|
||||
#define HAVE_GL_ARB_SYNC 1
|
||||
#endif
|
||||
|
||||
#ifdef USE_SDL
|
||||
#include "SDL_opengl.h"
|
||||
#endif
|
||||
|
||||
#ifdef OSX
|
||||
#include <OpenGL/CGLCurrent.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
||||
#ifdef DX_TO_GL_ABSTRACTION
|
||||
#ifndef WIN32
|
||||
#define Debugger DebuggerBreak
|
||||
#endif
|
||||
#undef CurrentTime
|
||||
|
||||
#if defined( USE_SDL )
|
||||
#include "SDL.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//===============================================================================
|
||||
// glue to call out to Obj-C land (these are in glmgrcocoa.mm)
|
||||
#ifdef OSX
|
||||
typedef void _PseudoNSGLContext; // aka NSOpenGLContext
|
||||
typedef _PseudoNSGLContext *PseudoNSGLContextPtr;
|
||||
|
||||
CGLContextObj GetCGLContextFromNSGL( PseudoNSGLContextPtr nsglCtx );
|
||||
#endif
|
||||
|
||||
// Set TOGL_SUPPORT_NULL_DEVICE to 1 to support the NULL ref device
|
||||
#define TOGL_SUPPORT_NULL_DEVICE 0
|
||||
|
||||
#if TOGL_SUPPORT_NULL_DEVICE
|
||||
#define TOGL_NULL_DEVICE_CHECK if( m_params.m_deviceType == D3DDEVTYPE_NULLREF ) return S_OK;
|
||||
#define TOGL_NULL_DEVICE_CHECK_RET_VOID if( m_params.m_deviceType == D3DDEVTYPE_NULLREF ) return;
|
||||
#else
|
||||
#define TOGL_NULL_DEVICE_CHECK
|
||||
#define TOGL_NULL_DEVICE_CHECK_RET_VOID
|
||||
#endif
|
||||
|
||||
// GL_ENABLE_INDEX_VERIFICATION enables index range verification on all dynamic IB/VB's (obviously slow)
|
||||
#define GL_ENABLE_INDEX_VERIFICATION 0
|
||||
|
||||
// GL_ENABLE_UNLOCK_BUFFER_OVERWRITE_DETECTION (currently win32 only) - If 1, VirtualAlloc/VirtualProtect is used to detect cases where the app locks a buffer, copies the ptr away, unlocks, then tries to later write to the buffer.
|
||||
#define GL_ENABLE_UNLOCK_BUFFER_OVERWRITE_DETECTION 0
|
||||
|
||||
#define GL_BATCH_TELEMETRY_ZONES 0
|
||||
|
||||
// GL_BATCH_PERF_ANALYSIS - Enables gl_batch_vis, and various per-batch telemetry statistics messages.
|
||||
#define GL_BATCH_PERF_ANALYSIS 0
|
||||
#define GL_BATCH_PERF_ANALYSIS_WRITE_PNGS 0
|
||||
|
||||
// GL_TELEMETRY_ZONES - Causes every single OpenGL call to generate a telemetry event
|
||||
#define GL_TELEMETRY_ZONES 0
|
||||
|
||||
// GL_DUMP_ALL_API_CALLS - Causes a debug message to be printed for every API call if s_bDumpCalls bool is set to 1
|
||||
#define GL_DUMP_ALL_API_CALLS 0
|
||||
|
||||
// Must also enable PIX_ENABLE to use GL_TELEMETRY_GPU_ZONES.
|
||||
#define GL_TELEMETRY_GPU_ZONES 0
|
||||
|
||||
// Records global # of OpenGL calls/total cycles spent inside GL
|
||||
#define GL_TRACK_API_TIME GL_BATCH_PERF_ANALYSIS
|
||||
|
||||
#define GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS ( GL_TELEMETRY_ZONES || GL_TRACK_API_TIME || GL_DUMP_ALL_API_CALLS )
|
||||
|
||||
#if GL_BATCH_PERF_ANALYSIS
|
||||
#define GL_BATCH_PERF(...) __VA_ARGS__
|
||||
#else
|
||||
#define GL_BATCH_PERF(...)
|
||||
#endif
|
||||
|
||||
#define kGLMUserClipPlanes 2
|
||||
#define kGLMScratchFBOCount 4
|
||||
|
||||
#endif // DX_TO_GL_ABSTRACTION
|
||||
|
||||
#endif // GLBASE_H
|
403
public/togles/linuxwin/glentrypoints.h
Normal file
403
public/togles/linuxwin/glentrypoints.h
Normal file
@ -0,0 +1,403 @@
|
||||
//========= 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.
|
||||
//
|
||||
// glentrypoints.h
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef GLENTRYPOINTS_H
|
||||
#define GLENTRYPOINTS_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef DX_TO_GL_ABSTRACTION
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#include "tier0/vprof_telemetry.h"
|
||||
#include "interface.h"
|
||||
#include "togl/rendermechanism.h"
|
||||
|
||||
void *VoidFnPtrLookup_GlMgr(const char *fn, bool &okay, const bool bRequired, void *fallback=NULL);
|
||||
|
||||
#if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS
|
||||
class CGLExecuteHelperBase
|
||||
{
|
||||
public:
|
||||
inline void StartCall(const char *pName);
|
||||
inline void StopCall(const char *pName);
|
||||
#if GL_TRACK_API_TIME
|
||||
TmU64 m_nStartTime;
|
||||
#endif
|
||||
};
|
||||
|
||||
template < class FunctionType, typename Result >
|
||||
class CGLExecuteHelper : public CGLExecuteHelperBase
|
||||
{
|
||||
public:
|
||||
inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(); StopCall(pName); }
|
||||
template<typename A> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a); StopCall(pName); }
|
||||
template<typename A, typename B> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b); StopCall(pName); }
|
||||
template<typename A, typename B, typename C> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); }
|
||||
|
||||
inline operator Result() const { return m_Result; }
|
||||
inline operator char*() const { return (char*)m_Result; }
|
||||
|
||||
FunctionType m_pFn;
|
||||
|
||||
Result m_Result;
|
||||
};
|
||||
|
||||
template < class FunctionType>
|
||||
class CGLExecuteHelper<FunctionType, void> : public CGLExecuteHelperBase
|
||||
{
|
||||
public:
|
||||
inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(); StopCall(pName); }
|
||||
template<typename A> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a); StopCall(pName); }
|
||||
template<typename A, typename B> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b); StopCall(pName); }
|
||||
template<typename A, typename B, typename C> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); }
|
||||
template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J> inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); }
|
||||
|
||||
FunctionType m_pFn;
|
||||
};
|
||||
#endif
|
||||
|
||||
template < class FunctionType, typename Result >
|
||||
class CDynamicFunctionOpenGLBase
|
||||
{
|
||||
public:
|
||||
// Construct with a NULL function pointer. You must manually call
|
||||
// Lookup() before you can call a dynamic function through this interface.
|
||||
CDynamicFunctionOpenGLBase() : m_pFn(NULL) {}
|
||||
|
||||
// Construct and do a lookup right away. You will need to make sure that
|
||||
// the lookup actually succeeded, as the gl library might have failed to load
|
||||
// or (fn) might not exist in it.
|
||||
CDynamicFunctionOpenGLBase(const char *fn, FunctionType fallback=NULL) : m_pFn(NULL)
|
||||
{
|
||||
Lookup(fn, fallback);
|
||||
}
|
||||
|
||||
// Construct and do a lookup right away. See comments in Lookup() about what (okay) does.
|
||||
CDynamicFunctionOpenGLBase(const char *fn, bool &okay, FunctionType fallback=NULL) : m_pFn(NULL)
|
||||
{
|
||||
Lookup(fn, okay, fallback);
|
||||
}
|
||||
|
||||
// Load library if necessary, look up symbol. Returns true and sets
|
||||
// m_pFn on successful lookup, returns false otherwise. If the
|
||||
// function pointer is already looked up, this return true immediately.
|
||||
// Use Reset() first if you want to look up the symbol again.
|
||||
// This function will return false immediately unless (okay) is true.
|
||||
// This allows you to chain lookups like this:
|
||||
// bool okay = true;
|
||||
// x.Lookup(lib, "x", okay);
|
||||
// y.Lookup(lib, "y", okay);
|
||||
// z.Lookup(lib, "z", okay);
|
||||
// if (okay) { printf("All functions were loaded successfully!\n"); }
|
||||
// If you supply a fallback, it'll be used if the lookup fails (and if
|
||||
// non-NULL, means this will always return (okay)).
|
||||
bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL)
|
||||
{
|
||||
if (!okay)
|
||||
return false;
|
||||
else if (this->m_pFn == NULL)
|
||||
{
|
||||
this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, false, (void *) fallback);
|
||||
this->SetFuncName( fn );
|
||||
}
|
||||
okay = m_pFn != NULL;
|
||||
return okay;
|
||||
}
|
||||
|
||||
// Load library if necessary, look up symbol. Returns true and sets
|
||||
// m_pFn on successful lookup, returns false otherwise. If the
|
||||
// function pointer is already looked up, this return true immediately.
|
||||
// Use Reset() first if you want to look up the symbol again.
|
||||
// This function will return false immediately unless (okay) is true.
|
||||
// If you supply a fallback, it'll be used if the lookup fails (and if
|
||||
// non-NULL, means this will always return true).
|
||||
bool Lookup(const char *fn, FunctionType fallback=NULL)
|
||||
{
|
||||
bool okay = true;
|
||||
return Lookup(fn, okay, fallback);
|
||||
}
|
||||
|
||||
// Invalidates the current lookup. Makes the function pointer NULL. You
|
||||
// will need to call Lookup() before you can call a dynamic function
|
||||
// through this interface again.
|
||||
void Reset() { m_pFn = NULL; }
|
||||
|
||||
// Force this to be a specific function pointer.
|
||||
void Force(FunctionType ptr) { m_pFn = ptr; }
|
||||
|
||||
// Retrieve the actual function pointer.
|
||||
FunctionType Pointer() const { return m_pFn; }
|
||||
|
||||
#if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS
|
||||
#if GL_TELEMETRY_ZONES || GL_DUMP_ALL_API_CALLS
|
||||
#define GL_FUNC_NAME m_szName
|
||||
#else
|
||||
#define GL_FUNC_NAME ""
|
||||
#endif
|
||||
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() () const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME ); }
|
||||
|
||||
template<typename T>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a); }
|
||||
|
||||
template<typename T, typename U>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b); }
|
||||
|
||||
template<typename T, typename U, typename V>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c ) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c); }
|
||||
|
||||
template<typename T, typename U, typename V, typename W>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d); }
|
||||
|
||||
template<typename T, typename U, typename V, typename W, typename X>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e); }
|
||||
|
||||
template<typename T, typename U, typename V, typename W, typename X, typename Y>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f); }
|
||||
|
||||
template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f, Z g) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g); }
|
||||
|
||||
template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z, typename A>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f, Z g, A h) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h); }
|
||||
|
||||
template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z, typename A, typename B>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i); }
|
||||
|
||||
template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z, typename A, typename B, typename C>
|
||||
inline CGLExecuteHelper<FunctionType, Result> operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i, C j) const { return CGLExecuteHelper<FunctionType, Result>(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i, j); }
|
||||
#else
|
||||
operator FunctionType() const { return m_pFn; }
|
||||
#endif
|
||||
|
||||
// Can be used to verify that we have an actual function looked up and
|
||||
// ready to call: if (!MyDynFunc) { printf("Function not found!\n"); }
|
||||
operator bool () const { return m_pFn != NULL; }
|
||||
bool operator !() const { return m_pFn == NULL; }
|
||||
|
||||
protected:
|
||||
FunctionType m_pFn;
|
||||
|
||||
#if GL_TELEMETRY_ZONES || GL_DUMP_ALL_API_CALLS
|
||||
char m_szName[32];
|
||||
inline void SetFuncName(const char *pFn) { V_strncpy( m_szName, pFn, sizeof( m_szName ) ); }
|
||||
#else
|
||||
inline void SetFuncName(const char *pFn) { (void)pFn; }
|
||||
#endif
|
||||
};
|
||||
|
||||
// This works a lot like CDynamicFunctionMustInit, but we use SDL_GL_GetProcAddress().
|
||||
template < const bool bRequired, class FunctionType, typename Result >
|
||||
class CDynamicFunctionOpenGL : public CDynamicFunctionOpenGLBase< FunctionType, Result >
|
||||
{
|
||||
private: // forbid default constructor.
|
||||
CDynamicFunctionOpenGL() {}
|
||||
|
||||
public:
|
||||
CDynamicFunctionOpenGL(const char *fn, FunctionType fallback=NULL)
|
||||
{
|
||||
bool okay = true;
|
||||
Lookup(fn, okay, fallback);
|
||||
this->SetFuncName( fn );
|
||||
}
|
||||
|
||||
CDynamicFunctionOpenGL(const char *fn, bool &okay, FunctionType fallback=NULL)
|
||||
{
|
||||
Lookup(fn, okay, fallback);
|
||||
this->SetFuncName( fn );
|
||||
}
|
||||
|
||||
// Please note this is not virtual.
|
||||
// !!! FIXME: we might want to fall back and try "EXT" or "ARB" versions in some case.
|
||||
bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL)
|
||||
{
|
||||
if (this->m_pFn == NULL)
|
||||
{
|
||||
this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, bRequired, (void *) fallback);
|
||||
this->SetFuncName( fn );
|
||||
}
|
||||
return okay;
|
||||
}
|
||||
};
|
||||
|
||||
enum GLDriverStrings_t
|
||||
{
|
||||
cGLVendorString,
|
||||
cGLRendererString,
|
||||
cGLVersionString,
|
||||
cGLExtensionsString,
|
||||
|
||||
cGLTotalDriverStrings
|
||||
};
|
||||
|
||||
enum GLDriverProvider_t
|
||||
{
|
||||
cGLDriverProviderUnknown,
|
||||
cGLDriverProviderNVIDIA,
|
||||
cGLDriverProviderAMD,
|
||||
cGLDriverProviderIntel,
|
||||
cGLDriverProviderIntelOpenSource,
|
||||
cGLDriverProviderApple,
|
||||
|
||||
cGLTotalDriverProviders
|
||||
};
|
||||
|
||||
// This provides all the entry points for a given OpenGL context.
|
||||
// ENTRY POINTS ARE ONLY VALID FOR THE CONTEXT THAT WAS CURRENT WHEN
|
||||
// YOU LOOKED THEM UP. 99% of the time, this is not a problem, but
|
||||
// that 1% is really hard to track down. Always access the GL
|
||||
// through this class!
|
||||
class COpenGLEntryPoints
|
||||
{
|
||||
COpenGLEntryPoints( const COpenGLEntryPoints & );
|
||||
COpenGLEntryPoints &operator= ( const COpenGLEntryPoints & );
|
||||
|
||||
public:
|
||||
// The GL context you are looking up entry points for must be current when you construct this object!
|
||||
COpenGLEntryPoints();
|
||||
~COpenGLEntryPoints();
|
||||
|
||||
void ClearEntryPoints();
|
||||
uint64 m_nTotalGLCycles, m_nTotalGLCalls;
|
||||
|
||||
int m_nOpenGLVersionMajor; // if GL_VERSION is 2.1.0, this will be set to 2.
|
||||
int m_nOpenGLVersionMinor; // if GL_VERSION is 2.1.0, this will be set to 1.
|
||||
int m_nOpenGLVersionPatch; // if GL_VERSION is 2.1.0, this will be set to 0.
|
||||
bool m_bHave_OpenGL;
|
||||
|
||||
char *m_pGLDriverStrings[cGLTotalDriverStrings];
|
||||
GLDriverProvider_t m_nDriverProvider;
|
||||
|
||||
#ifdef OSX
|
||||
#define GL_EXT(x,glmajor,glminor) bool m_bHave_##x;
|
||||
#define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (*) arg, ret > fn;
|
||||
#define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (*) arg, void > fn;
|
||||
#else
|
||||
#define GL_EXT(x,glmajor,glminor) bool m_bHave_##x;
|
||||
#define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (APIENTRY *) arg, ret > fn;
|
||||
#define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (APIENTRY *) arg, void > fn;
|
||||
#endif
|
||||
#include "togl/glfuncs.inl"
|
||||
#undef GL_FUNC_VOID
|
||||
#undef GL_FUNC
|
||||
#undef GL_EXT
|
||||
|
||||
bool HasSwapTearExtension() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return m_bHave_WGL_EXT_swap_control_tear;
|
||||
#else
|
||||
return m_bHave_GLX_EXT_swap_control_tear;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// This will be set to the current OpenGL context's entry points.
|
||||
extern COpenGLEntryPoints *gGL;
|
||||
typedef void * (*GL_GetProcAddressCallbackFunc_t)(const char *, bool &, const bool, void *);
|
||||
|
||||
#ifdef TOGL_DLL_EXPORT
|
||||
DLL_EXPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory );
|
||||
DLL_EXPORT void ToGLDisconnectLibraries();
|
||||
DLL_EXPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback);
|
||||
DLL_EXPORT void ClearOpenGLEntryPoints();
|
||||
#else
|
||||
DLL_IMPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory );
|
||||
DLL_IMPORT void ToGLDisconnectLibraries();
|
||||
DLL_IMPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback);
|
||||
DLL_IMPORT void ClearOpenGLEntryPoints();
|
||||
#endif
|
||||
|
||||
#if GL_USE_EXECUTE_HELPER_FOR_ALL_API_CALLS
|
||||
inline void CGLExecuteHelperBase::StartCall(const char *pName)
|
||||
{
|
||||
(void)pName;
|
||||
|
||||
#if GL_TELEMETRY_ZONES
|
||||
tmEnter( TELEMETRY_LEVEL3, TMZF_NONE, pName );
|
||||
#endif
|
||||
|
||||
#if GL_TRACK_API_TIME
|
||||
m_nStartTime = tmFastTime();
|
||||
#endif
|
||||
|
||||
#if GL_DUMP_ALL_API_CALLS
|
||||
static bool s_bDumpCalls;
|
||||
if ( s_bDumpCalls )
|
||||
{
|
||||
char buf[128];
|
||||
buf[0] = 'G';
|
||||
buf[1] = 'L';
|
||||
buf[2] = ':';
|
||||
size_t l = strlen( pName );
|
||||
memcpy( buf + 3, pName, l );
|
||||
buf[3 + l] = '\n';
|
||||
buf[4 + l] = '\0';
|
||||
Plat_DebugString( buf );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void CGLExecuteHelperBase::StopCall(const char *pName)
|
||||
{
|
||||
#if GL_TRACK_API_TIME
|
||||
uint64 nTotalCycles = tmFastTime() - m_nStartTime;
|
||||
#endif
|
||||
|
||||
#if GL_TELEMETRY_ZONES
|
||||
tmLeave( TELEMETRY_LEVEL3 );
|
||||
#endif
|
||||
|
||||
#if GL_TRACK_API_TIME
|
||||
//double flMilliseconds = g_Telemetry.flRDTSCToMilliSeconds * nTotalCycles;
|
||||
if (gGL)
|
||||
{
|
||||
gGL->m_nTotalGLCycles += nTotalCycles;
|
||||
gGL->m_nTotalGLCalls++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // DX_TO_GL_ABSTRACTION
|
||||
|
||||
#endif // GLENTRYPOINTS_H
|
277
public/togles/linuxwin/glfuncs.h
Normal file
277
public/togles/linuxwin/glfuncs.h
Normal file
@ -0,0 +1,277 @@
|
||||
//========= 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.
|
||||
// !!! FIXME: Some of these aren't base OpenGL...pick out the extensions.
|
||||
// !!! FIXME: Also, look up these -1, -1 versions numbers.
|
||||
GL_FUNC(OpenGL,true,GLenum,glGetError,(void),())
|
||||
GL_FUNC_VOID(OpenGL,true,glActiveTexture,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glAlphaFunc,(GLenum a,GLclampf b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glAttachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glBegin,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glBindAttribLocationARB,(GLhandleARB a,GLuint b,const GLcharARB *c),(a,b,c))
|
||||
GL_FUNC_VOID(OpenGL,true,glBindBufferARB,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glBindProgramARB,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glBindTexture,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glBlendColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glBlendEquation,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glBlendFunc,(GLenum a,GLenum b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glBufferDataARB,(GLenum a,GLsizeiptrARB b,const GLvoid *c,GLenum d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glClear,(GLbitfield a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glClearColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glClearDepth,(GLclampd a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glClearStencil,(GLint a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glClipPlane,(GLenum a,const GLdouble *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glColorMask,(GLboolean a,GLboolean b,GLboolean c,GLboolean d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glCompileShaderARB,(GLhandleARB a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glCompressedTexImage2D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLint f,GLsizei g,const GLvoid *h),(a,b,c,d,e,f,g,h))
|
||||
GL_FUNC_VOID(OpenGL,true,glCompressedTexImage3D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLsizei h,const GLvoid *i),(a,b,c,d,e,f,g,h,i))
|
||||
GL_FUNC(OpenGL,true,GLhandleARB,glCreateProgramObjectARB,(void),())
|
||||
GL_FUNC(OpenGL,true,GLhandleARB,glCreateShaderObjectARB,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glDeleteBuffersARB,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glDeleteObjectARB,(GLhandleARB a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glDeleteProgramsARB,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glDeleteQueriesARB,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glDeleteShader,(GLuint a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glDeleteTextures,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glDepthFunc,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glDepthMask,(GLboolean a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glDepthRange,(GLclampd a,GLclampd b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glDetachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glDisable,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glDisableVertexAttribArray,(GLuint a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glDrawArrays,(GLenum a,GLint b,GLsizei c),(a,b,c))
|
||||
GL_FUNC_VOID(OpenGL,true,glDrawBuffer,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glDrawBuffers,(GLsizei a,const GLenum *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glDrawRangeElements,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f),(a,b,c,d,e,f))
|
||||
#ifndef OSX // 10.6/GL 2.1 compatability
|
||||
GL_FUNC_VOID(OpenGL,true,glDrawRangeElementsBaseVertex,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f, GLenum g),(a,b,c,d,e,f,g))
|
||||
#endif
|
||||
GL_FUNC_VOID(OpenGL,true,glEnable,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glEnableVertexAttribArray,(GLuint a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glEnd,(void),())
|
||||
GL_FUNC_VOID(OpenGL,true,glFinish,(void),())
|
||||
GL_FUNC_VOID(OpenGL,true,glFlush,(void),())
|
||||
GL_FUNC_VOID(OpenGL,true,glFrontFace,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glGenBuffersARB,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glGenProgramsARB,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glGenQueriesARB,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glGenTextures,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetBooleanv,(GLenum a,GLboolean *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetCompressedTexImage,(GLenum a,GLint b,GLvoid *c),(a,b,c))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetDoublev,(GLenum a,GLdouble *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetFloatv,(GLenum a,GLfloat *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetInfoLogARB,(GLhandleARB a,GLsizei b,GLsizei *c,GLcharARB *d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetIntegerv,(GLenum a,GLint *b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetObjectParameterivARB,(GLhandleARB a,GLenum b,GLint *c),(a,b,c))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetProgramivARB,(GLenum a,GLenum b,GLint *c),(a,b,c))
|
||||
GL_FUNC(OpenGL,true,const GLubyte *,glGetString,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetTexImage,(GLenum a,GLint b,GLenum c,GLenum d,GLvoid *e),(a,b,c,d,e))
|
||||
GL_FUNC(OpenGL,true,GLint,glGetUniformLocationARB,(GLhandleARB a,const GLcharARB *b),(a,b))
|
||||
GL_FUNC(OpenGL,true,GLboolean,glIsEnabled,(GLenum a),(a))
|
||||
GL_FUNC(OpenGL,true,GLboolean,glIsTexture,(GLuint a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glLinkProgramARB,(GLhandleARB a),(a))
|
||||
GL_FUNC(OpenGL,true,GLvoid*,glMapBufferARB,(GLenum a,GLenum b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glOrtho,(GLdouble a,GLdouble b,GLdouble c,GLdouble d,GLdouble e,GLdouble f),(a,b,c,d,e,f))
|
||||
GL_FUNC_VOID(OpenGL,true,glPixelStorei,(GLenum a,GLint b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glPolygonMode,(GLenum a,GLenum b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glPolygonOffset,(GLfloat a,GLfloat b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glPopAttrib,(void),())
|
||||
GL_FUNC_VOID(OpenGL,true,glProgramStringARB,(GLenum a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glPushAttrib,(GLbitfield a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glReadBuffer,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glScissor,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glShaderSourceARB,(GLhandleARB a,GLsizei b,const GLcharARB **c,const GLint *d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glStencilFunc,(GLenum a,GLint b,GLuint c),(a,b,c))
|
||||
GL_FUNC_VOID(OpenGL,true,glStencilMask,(GLuint a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glStencilOp,(GLenum a,GLenum b,GLenum c),(a,b,c))
|
||||
GL_FUNC_VOID(OpenGL,true,glTexCoord2f,(GLfloat a,GLfloat b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glTexImage2D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLint f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i))
|
||||
GL_FUNC_VOID(OpenGL,true,glTexImage3D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLenum h,GLenum i,const GLvoid *j),(a,b,c,d,e,f,g,h,i,j))
|
||||
GL_FUNC_VOID(OpenGL,true,glTexParameterfv,(GLenum a,GLenum b,const GLfloat *c),(a,b,c))
|
||||
GL_FUNC_VOID(OpenGL,true,glTexParameteri,(GLenum a,GLenum b,GLint c),(a,b,c))
|
||||
GL_FUNC_VOID(OpenGL,true,glTexSubImage2D,(GLenum a,GLint b,GLint c,GLint d,GLsizei e,GLsizei f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i))
|
||||
GL_FUNC_VOID(OpenGL,true,glUniform1f,(GLint a,GLfloat b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glUniform1i,(GLint a,GLint b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glUniform1iARB,(GLint a,GLint b),(a,b))
|
||||
GL_FUNC_VOID(OpenGL,true,glUniform4fv,(GLint a,GLsizei b,const GLfloat *c),(a,b,c))
|
||||
GL_FUNC(OpenGL,true,GLboolean,glUnmapBuffer,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glUseProgram,(GLuint a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glVertex3f,(GLfloat a,GLfloat b,GLfloat c),(a,b,c))
|
||||
GL_FUNC_VOID(OpenGL,true,glVertexAttribPointer,(GLuint a,GLint b,GLenum c,GLboolean d,GLsizei e,const GLvoid *f),(a,b,c,d,e,f))
|
||||
GL_FUNC_VOID(OpenGL,true,glViewport,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glEnableClientState,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glDisableClientState,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glClientActiveTexture,(GLenum a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glVertexPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glTexCoordPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glProgramEnvParameters4fvEXT,(GLenum a,GLuint b,GLsizei c,const GLfloat *d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glColor4sv,(const GLshort *a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glStencilOpSeparate,(GLenum a,GLenum b,GLenum c,GLenum d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glStencilFuncSeparate,(GLenum a,GLenum b,GLint c,GLuint d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetTexLevelParameteriv,(GLenum a,GLint b,GLenum c,GLint *d),(a,b,c,d))
|
||||
GL_FUNC_VOID(OpenGL,true,glColor4f,(GLfloat a,GLfloat b,GLfloat c,GLfloat d),(a,b,c,d))
|
||||
GL_EXT(GL_EXT_framebuffer_object,-1,-1)
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindFramebufferEXT,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindRenderbufferEXT,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC(GL_EXT_framebuffer_object,false,GLenum,glCheckFramebufferStatusEXT,(GLenum a),(a))
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteRenderbuffersEXT,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferRenderbufferEXT,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d))
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture2DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e))
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture3DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f))
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenFramebuffersEXT,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenRenderbuffersEXT,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteFramebuffersEXT,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_EXT(GL_EXT_framebuffer_blit,-1,-1)
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_blit,false,glBlitFramebufferEXT,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j))
|
||||
GL_EXT(GL_EXT_framebuffer_multisample,-1,-1)
|
||||
GL_FUNC_VOID(GL_EXT_framebuffer_multisample,false,glRenderbufferStorageMultisampleEXT,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e))
|
||||
GL_EXT(GL_APPLE_fence,-1,-1)
|
||||
GL_FUNC(GL_APPLE_fence,false,GLboolean,glTestFenceAPPLE,(GLuint a),(a))
|
||||
GL_FUNC_VOID(GL_APPLE_fence,false,glSetFenceAPPLE,(GLuint a),(a))
|
||||
GL_FUNC_VOID(GL_APPLE_fence,false,glFinishFenceAPPLE,(GLuint a),(a))
|
||||
GL_FUNC_VOID(GL_APPLE_fence,false,glDeleteFencesAPPLE,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(GL_APPLE_fence,false,glGenFencesAPPLE,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_EXT(GL_NV_fence,-1,-1)
|
||||
GL_FUNC(GL_NV_fence,false,GLboolean,glTestFenceNV,(GLuint a),(a))
|
||||
GL_FUNC_VOID(GL_NV_fence,false,glSetFenceNV,(GLuint a,GLenum b),(a,b))
|
||||
GL_FUNC_VOID(GL_NV_fence,false,glFinishFenceNV,(GLuint a),(a))
|
||||
GL_FUNC_VOID(GL_NV_fence,false,glDeleteFencesNV,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(GL_NV_fence,false,glGenFencesNV,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_EXT(GL_ARB_sync,3,2)
|
||||
#ifdef HAVE_GL_ARB_SYNC
|
||||
GL_FUNC_VOID(GL_ARB_sync,false,glGetSynciv,(GLsync a, GLenum b, GLsizei c, GLsizei *d, GLint *e),(a,b,c,d,e))
|
||||
GL_FUNC(GL_ARB_sync,false,GLenum,glClientWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c))
|
||||
GL_FUNC_VOID(GL_ARB_sync,false,glWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c))
|
||||
GL_FUNC_VOID(GL_ARB_sync,false,glDeleteSync,(GLsync a),(a))
|
||||
GL_FUNC(GL_ARB_sync,false,GLsync,glFenceSync,(GLenum a, GLbitfield b),(a,b))
|
||||
#endif
|
||||
GL_EXT(GL_EXT_draw_buffers2,-1,-1)
|
||||
GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glColorMaskIndexedEXT,(GLuint a,GLboolean b,GLboolean c,GLboolean d,GLboolean e),(a,b,c,d,e))
|
||||
GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glEnableIndexedEXT,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glDisableIndexedEXT,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC_VOID(GL_EXT_draw_buffers2,true,glGetBooleanIndexedvEXT,(GLenum a,GLuint b,GLboolean *c),(a,b,c))
|
||||
GL_EXT(GL_EXT_bindable_uniform,-1,-1)
|
||||
GL_FUNC_VOID(GL_EXT_bindable_uniform,false,glUniformBufferEXT,(GLuint a,GLint b,GLuint c),(a,b,c))
|
||||
GL_FUNC(GL_EXT_bindable_uniform,false,int,glGetUniformBufferSizeEXT,(GLenum a, GLenum b),(a,b))
|
||||
GL_FUNC(GL_EXT_bindable_uniform,false,GLintptr,glGetUniformOffsetEXT,(GLenum a, GLenum b),(a,b))
|
||||
GL_EXT(GL_APPLE_flush_buffer_range,-1,-1)
|
||||
GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glBufferParameteriAPPLE,(GLenum a,GLenum b,GLint c),(a,b,c))
|
||||
GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glFlushMappedBufferRangeAPPLE,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c))
|
||||
GL_EXT(GL_ARB_map_buffer_range,-1,-1)
|
||||
GL_FUNC(GL_ARB_map_buffer_range,false,void*,glMapBufferRange,(GLenum a,GLintptr b,GLsizeiptr c,GLbitfield d),(a,b,c,d))
|
||||
GL_FUNC_VOID(GL_ARB_map_buffer_range,false,glFlushMappedBufferRange,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c))
|
||||
GL_EXT(GL_ARB_vertex_buffer_object,-1,-1)
|
||||
GL_FUNC_VOID(GL_ARB_vertex_buffer_object,true,glBufferSubData,(GLenum a,GLintptr b,GLsizeiptr c,const GLvoid *d),(a,b,c,d))
|
||||
GL_EXT(GL_ARB_occlusion_query,-1,-1)
|
||||
GL_FUNC_VOID(GL_ARB_occlusion_query,false,glBeginQueryARB,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC_VOID(GL_ARB_occlusion_query,false,glEndQueryARB,(GLenum a),(a))
|
||||
GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectivARB,(GLuint a,GLenum b,GLint *c),(a,b,c))
|
||||
GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectuivARB,(GLuint a,GLenum b,GLuint *c),(a,b,c))
|
||||
GL_EXT(GL_APPLE_texture_range,-1,-1)
|
||||
GL_FUNC_VOID(GL_APPLE_texture_range,false,glTextureRangeAPPLE,(GLenum a,GLsizei b,void *c),(a,b,c))
|
||||
GL_FUNC_VOID(GL_APPLE_texture_range,false,glGetTexParameterPointervAPPLE,(GLenum a,GLenum b,void* *c),(a,b,c))
|
||||
GL_EXT(GL_APPLE_client_storage,-1,-1)
|
||||
GL_EXT(GL_ARB_uniform_buffer,-1,-1)
|
||||
GL_EXT(GL_ARB_vertex_array_bgra,-1,-1)
|
||||
GL_EXT(GL_EXT_vertex_array_bgra,-1,-1)
|
||||
GL_EXT(GL_ARB_framebuffer_object,3,0)
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindFramebuffer,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindRenderbuffer,(GLenum a,GLuint b),(a,b))
|
||||
GL_FUNC(GL_ARB_framebuffer_object,false,GLenum,glCheckFramebufferStatus,(GLenum a),(a))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteRenderbuffers,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferRenderbuffer,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture2D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture3D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenFramebuffers,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenRenderbuffers,(GLsizei a,GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteFramebuffers,(GLsizei a,const GLuint *b),(a,b))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBlitFramebuffer,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j))
|
||||
GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glRenderbufferStorageMultisample,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e))
|
||||
GL_EXT(GL_GREMEDY_string_marker,-1,-1)
|
||||
GL_FUNC_VOID(GL_GREMEDY_string_marker,false,glStringMarkerGREMEDY,(GLsizei a,const void *b),(a,b))
|
||||
GL_EXT(GL_ARB_debug_output,-1,-1)
|
||||
#ifdef OSX
|
||||
GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageCallbackARB,(void ( *a)(GLenum, GLenum , GLuint , GLenum , GLsizei , const GLchar* , GLvoid*) ,void* b),(a,b))
|
||||
#else
|
||||
GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageCallbackARB,(void (APIENTRY *a)(GLenum, GLenum , GLuint , GLenum , GLsizei , const GLchar* , GLvoid*) ,void* b),(a,b))
|
||||
#endif
|
||||
GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageControlARB,(GLenum a, GLenum b, GLenum c, GLsizei d, const GLuint* e, GLboolean f),(a,b,c,d,e,f))
|
||||
|
||||
GL_EXT(GL_EXT_direct_state_access,-1,-1)
|
||||
GL_FUNC_VOID(GL_EXT_direct_state_access,false,glBindMultiTextureEXT,(GLenum a,GLuint b, GLuint c),(a,b,c))
|
||||
GL_EXT(GL_NV_bindless_texture,-1,-1)
|
||||
|
||||
#ifndef OSX
|
||||
GL_FUNC_VOID(OpenGL, true, glGenSamplers, (GLuint a, GLuint *b), (a, b))
|
||||
GL_FUNC_VOID(OpenGL, true, glDeleteSamplers, (GLsizei a, const GLuint *b), (a, b))
|
||||
GL_FUNC_VOID(OpenGL, true, glBindSampler, (GLuint a, GLuint b), (a, b))
|
||||
GL_FUNC_VOID(OpenGL, true, glSamplerParameteri, (GLuint a, GLenum b, GLint c), (a, b, c))
|
||||
GL_FUNC_VOID(OpenGL, true, glSamplerParameterf, (GLuint a, GLenum b, GLfloat c), (a, b, c))
|
||||
GL_FUNC_VOID(OpenGL, true, glSamplerParameterfv, (GLuint a, GLenum b, const GLfloat *c), (a, b, c))
|
||||
GL_FUNC(GL_NV_bindless_texture, false, GLuint64, glGetTextureHandleNV, (GLuint texture), (texture))
|
||||
GL_FUNC(GL_NV_bindless_texture, false, GLuint64, glGetTextureSamplerHandleNV, (GLuint texture, GLuint sampler), (texture, sampler))
|
||||
GL_FUNC_VOID(GL_NV_bindless_texture, false, glMakeTextureHandleResidentNV, (GLuint64 handle), (handle))
|
||||
GL_FUNC_VOID(GL_NV_bindless_texture, false, glMakeTextureHandleNonResidentNV, (GLuint64 handle), (handle))
|
||||
GL_FUNC_VOID(GL_NV_bindless_texture, false, glUniformHandleui64NV, (GLint location, GLuint64 value), (location, value))
|
||||
GL_FUNC_VOID(GL_NV_bindless_texture, false, glUniformHandleui64vNV, (int location, GLsizei count, const GLuint64 *value), (location count, value))
|
||||
GL_FUNC_VOID(GL_NV_bindless_texture, false, glProgramUniformHandleui64NV, (GLuint program, GLint location, GLuint64 value), (program, location, value))
|
||||
GL_FUNC_VOID(GL_NV_bindless_texture, false, glProgramUniformHandleui64vNV, (GLuint program, GLint location, GLsizei count, const GLuint64 *values), (program, location, count, values))
|
||||
GL_FUNC(GL_NV_bindless_texture, false, GLboolean, glIsTextureHandleResidentNV, (GLuint64 handle), (handle))
|
||||
GL_FUNC_VOID(OpenGL,true,glGenQueries,(GLsizei n, GLuint *ids), (n, ids))
|
||||
GL_FUNC_VOID(OpenGL,true,glDeleteQueries,(GLsizei n, const GLuint *ids),(n, ids))
|
||||
GL_FUNC_VOID(OpenGL,true,glBeginQuery,(GLenum target, GLuint id), (target, id))
|
||||
GL_FUNC_VOID(OpenGL,true,glEndQuery,(GLenum target), (target))
|
||||
GL_FUNC_VOID(OpenGL,true,glQueryCounter,(GLuint id, GLenum target), (id, target))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetQueryObjectiv,(GLuint id, GLenum pname, GLint *params), (id, pname, params))
|
||||
GL_FUNC_VOID(OpenGL,true,glGetQueryObjectui64v,(GLuint id, GLenum pname, GLuint64 *params), (id, pname, params))
|
||||
GL_FUNC_VOID(OpenGL,true,glCopyBufferSubData,(GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size),(readtarget, writetarget, readoffset, writeoffset, size))
|
||||
#endif // !OSX
|
||||
|
||||
GL_EXT(GL_AMD_pinned_memory,-1,-1)
|
||||
GL_EXT(GL_EXT_framebuffer_multisample_blit_scaled,-1,-1)
|
||||
|
||||
#ifndef OSX
|
||||
GL_FUNC_VOID(OpenGL,true,glGenVertexArrays,(GLsizei n, GLuint *arrays),(n, arrays))
|
||||
GL_FUNC_VOID(OpenGL,true,glDeleteVertexArrays,(GLsizei n, GLuint *arrays),(n, arrays))
|
||||
GL_FUNC_VOID(OpenGL,true,glBindVertexArray,(GLuint a),(a))
|
||||
#endif // !OSX
|
||||
|
||||
GL_EXT(GL_EXT_texture_sRGB_decode,-1,-1)
|
||||
GL_FUNC_VOID(OpenGL,true,glPushClientAttrib,(GLbitfield a),(a))
|
||||
GL_FUNC_VOID(OpenGL,true,glPopClientAttrib,(void),())
|
||||
GL_EXT(GL_NVX_gpu_memory_info,-1,-1)
|
||||
GL_EXT(GL_ATI_meminfo,-1,-1)
|
||||
GL_EXT(GL_EXT_texture_compression_s3tc,-1,-1)
|
||||
GL_EXT(GL_EXT_texture_compression_dxt1,-1,-1)
|
||||
GL_EXT(GL_ANGLE_texture_compression_dxt3,-1,-1)
|
||||
GL_EXT(GL_ANGLE_texture_compression_dxt5,-1,-1)
|
||||
|
||||
GL_EXT( GL_ARB_buffer_storage, 4, 4 )
|
||||
GL_FUNC_VOID( GL_ARB_buffer_storage, false, glBufferStorage, (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags), (target, size, data, flags) )
|
||||
|
||||
// This one is an OS extension. We'll add a little helper function to look for it.
|
||||
#ifdef _WIN32
|
||||
GL_EXT(WGL_EXT_swap_control_tear,-1,-1)
|
||||
#else
|
||||
GL_EXT(GLX_EXT_swap_control_tear,-1,-1)
|
||||
#endif
|
181
public/togles/linuxwin/glmdebug.h
Normal file
181
public/togles/linuxwin/glmdebug.h
Normal file
@ -0,0 +1,181 @@
|
||||
//========= 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.
|
||||
#ifndef GLMDEBUG_H
|
||||
#define GLMDEBUG_H
|
||||
|
||||
#include "tier0/platform.h"
|
||||
#if defined( OSX )
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
||||
#ifdef POSIX
|
||||
#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
|
||||
|
||||
|
||||
//===============================================================================
|
||||
// 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 );
|
||||
|
||||
// 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 );
|
||||
|
||||
#ifdef TOGL_DLL_EXPORT
|
||||
// these will look at the string to guess its flavor: <, >, ---, -M-, -S-
|
||||
DLL_EXPORT void GLMPrintfVA( const char *fmt, va_list vargs );
|
||||
DLL_EXPORT void GLMPrintf( const char *fmt, ... );
|
||||
#else
|
||||
DLL_IMPORT void GLMPrintfVA( const char *fmt, va_list vargs );
|
||||
DLL_IMPORT void GLMPrintf( const char *fmt, ... );
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
#else
|
||||
#define GLMPRINTF(args)
|
||||
#define GLMPRINTSTR(args)
|
||||
#define GLMPRINTTEXT(args)
|
||||
#endif
|
||||
|
||||
|
||||
//===============================================================================
|
||||
// knob twiddling
|
||||
#ifdef TOGL_DLL_EXPORT
|
||||
DLL_EXPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value
|
||||
DLL_EXPORT float GLMKnobToggle( char *knobname );
|
||||
#else
|
||||
DLL_IMPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value
|
||||
DLL_IMPORT float GLMKnobToggle( char *knobname );
|
||||
#endif
|
||||
|
||||
//===============================================================================
|
||||
// other stuff
|
||||
|
||||
#if GLMDEBUG
|
||||
void GLMTriggerDebuggerBreak();
|
||||
inline void GLMDebugger( void )
|
||||
{
|
||||
if (GLMDebugChannelMask() & (1<<eDebugger))
|
||||
{
|
||||
DebuggerBreak();
|
||||
}
|
||||
|
||||
if (GLMDebugChannelMask() & (1<<eGLProfiler))
|
||||
{
|
||||
GLMTriggerDebuggerBreak();
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define GLMDebugger() do { } while(0)
|
||||
#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 );
|
||||
|
||||
void CheckGLError( int line );
|
||||
|
||||
#endif // GLMDEBUG_H
|
201
public/togles/linuxwin/glmdisplay.h
Normal file
201
public/togles/linuxwin/glmdisplay.h
Normal file
@ -0,0 +1,201 @@
|
||||
//========= 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.
|
||||
//
|
||||
// glmdisplay.h
|
||||
// display related stuff - used by both GLMgr and the CocoaMgr
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef GLMDISPLAY_H
|
||||
#define GLMDISPLAY_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_SDL
|
||||
#include "SDL_opengl.h"
|
||||
#endif
|
||||
|
||||
#ifdef OSX
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/CGLRenderers.h>
|
||||
#include <OpenGL/CGLCurrent.h>
|
||||
#endif
|
||||
|
||||
#ifdef MAC_OS_X_VERSION_10_9
|
||||
typedef uint32_t CGDirectDisplayID;
|
||||
typedef uint32_t CGOpenGLDisplayMask;
|
||||
typedef double CGRefreshRate;
|
||||
#endif
|
||||
|
||||
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
|
||||
{
|
||||
#ifdef OSX
|
||||
CGDirectDisplayID m_cgDisplayID;
|
||||
CGOpenGLDisplayMask m_glDisplayMask; // result of CGDisplayIDToOpenGLDisplayMask on the cg_displayID.
|
||||
#endif
|
||||
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_intelHD4000;
|
||||
|
||||
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_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;
|
||||
int m_maxVertexBindableUniforms;
|
||||
int m_maxFragmentBindableUniforms;
|
||||
int m_maxBindableUniformSize;
|
||||
|
||||
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
|
||||
bool m_badDriver108Intel; // this is the bad Intel HD4000 driver on 10.8 - intermittent crash on GLSL compilation.
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
157
public/togles/linuxwin/glmdisplaydb.h
Normal file
157
public/togles/linuxwin/glmdisplaydb.h
Normal file
@ -0,0 +1,157 @@
|
||||
//========= 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.
|
||||
#ifndef GLMDISPLAYDB_H
|
||||
#define GLMDISPLAYDB_H
|
||||
|
||||
#include "tier1/utlvector.h"
|
||||
|
||||
//===============================================================================
|
||||
// modes, displays, and renderers
|
||||
//===============================================================================
|
||||
|
||||
// GLMDisplayModeInfoFields is in glmdisplay.h
|
||||
|
||||
class GLMDisplayMode
|
||||
{
|
||||
public:
|
||||
GLMDisplayModeInfoFields m_info;
|
||||
|
||||
GLMDisplayMode( uint width, uint height, uint refreshHz );
|
||||
GLMDisplayMode() { };
|
||||
~GLMDisplayMode( void );
|
||||
|
||||
void Init( uint width, uint height, uint refreshHz );
|
||||
void Dump( int which );
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// GLMDisplayInfoFields is in glmdisplay.h
|
||||
|
||||
class GLMDisplayInfo
|
||||
{
|
||||
public:
|
||||
GLMDisplayInfoFields m_info;
|
||||
CUtlVector< GLMDisplayMode* > *m_modes; // starts out NULL, set by PopulateModes
|
||||
GLMDisplayMode m_DesktopMode;
|
||||
|
||||
#ifdef OSX
|
||||
GLMDisplayInfo( CGDirectDisplayID displayID, CGOpenGLDisplayMask displayMask );
|
||||
#else
|
||||
GLMDisplayInfo( void );
|
||||
#endif
|
||||
|
||||
~GLMDisplayInfo( void );
|
||||
|
||||
void PopulateModes( void );
|
||||
|
||||
void Dump( int which );
|
||||
|
||||
#ifdef OSX
|
||||
private:
|
||||
int m_display;
|
||||
#endif
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// GLMRendererInfoFields is in glmdisplay.h
|
||||
|
||||
class GLMRendererInfo
|
||||
{
|
||||
public:
|
||||
GLMRendererInfoFields m_info;
|
||||
#ifdef OSX
|
||||
CUtlVector< GLMDisplayInfo* > *m_displays; // starts out NULL, set by PopulateDisplays
|
||||
#else
|
||||
GLMDisplayInfo *m_display;
|
||||
#endif
|
||||
|
||||
#ifdef OSX
|
||||
GLMRendererInfo ( GLMRendererInfoFields *info );
|
||||
#else
|
||||
GLMRendererInfo ();
|
||||
#endif
|
||||
~GLMRendererInfo ( void );
|
||||
|
||||
#ifndef OSX
|
||||
void Init( GLMRendererInfoFields *info );
|
||||
#endif
|
||||
void PopulateDisplays();
|
||||
void Dump( int which );
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
#ifdef OSX
|
||||
// this is just a tuple describing fake adapters which are really renderer/display pairings.
|
||||
// dxabstract bridges the gap between the d3d adapter-centric world and the GL renderer+display world.
|
||||
// this makes it straightforward to handle cases like two video cards with two displays on one, and one on the other -
|
||||
// you get three fake adapters which represent each useful screen.
|
||||
|
||||
// the constraint that dxa will have to follow though, is that if the user wants to change their
|
||||
// display selection for full screen, they would only be able to pick on that has the same underlying renderer.
|
||||
// can't change fakeAdapter from one to another with different GL renderer under it. Screen hop but no card hop.
|
||||
|
||||
struct GLMFakeAdapter
|
||||
{
|
||||
int m_rendererIndex;
|
||||
int m_displayIndex;
|
||||
};
|
||||
#endif
|
||||
|
||||
class GLMDisplayDB
|
||||
{
|
||||
public:
|
||||
#ifdef OSX
|
||||
CUtlVector< GLMRendererInfo* > *m_renderers; // starts out NULL, set by PopulateRenderers
|
||||
CUtlVector< GLMFakeAdapter > m_fakeAdapters;
|
||||
#else
|
||||
GLMRendererInfo m_renderer;
|
||||
#endif
|
||||
|
||||
GLMDisplayDB ( void );
|
||||
~GLMDisplayDB ( void );
|
||||
|
||||
virtual void PopulateRenderers( void );
|
||||
virtual void PopulateFakeAdapters( uint realRendererIndex ); // fake adapters = one real adapter times however many displays are on it
|
||||
virtual void Populate( void );
|
||||
|
||||
// The info-get functions return false on success.
|
||||
virtual int GetFakeAdapterCount( void );
|
||||
virtual bool GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut );
|
||||
|
||||
virtual int GetRendererCount( void );
|
||||
virtual bool GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut );
|
||||
|
||||
virtual int GetDisplayCount( int rendererIndex );
|
||||
virtual bool GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut );
|
||||
|
||||
virtual int GetModeCount( int rendererIndex, int displayIndex );
|
||||
virtual bool GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut );
|
||||
|
||||
virtual void Dump( void );
|
||||
};
|
||||
|
||||
#endif // GLMDISPLAYDB_H
|
2435
public/togles/linuxwin/glmgr.h
Normal file
2435
public/togles/linuxwin/glmgr.h
Normal file
File diff suppressed because it is too large
Load Diff
332
public/togles/linuxwin/glmgrbasics.h
Normal file
332
public/togles/linuxwin/glmgrbasics.h
Normal file
@ -0,0 +1,332 @@
|
||||
//========= 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.
|
||||
//
|
||||
// glmgrbasics.h
|
||||
// types, common headers, forward declarations, utilities
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef GLMBASICS_H
|
||||
#define GLMBASICS_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_SDL
|
||||
#include "SDL_opengl.h"
|
||||
#endif
|
||||
|
||||
#ifdef OSX
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/CGLRenderers.h>
|
||||
#include <OpenGL/CGLCurrent.h>
|
||||
#include <AvailabilityMacros.h>
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_9
|
||||
#include <OpenGL/CGLProfiler.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "tier0/platform.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 "dxabstract_types.h"
|
||||
|
||||
struct GLMRect;
|
||||
typedef void *PseudoGLContextPtr;
|
||||
|
||||
// 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;
|
||||
|
||||
// these will look at the string to guess its flavor: <, >, ---, -M-, -S-
|
||||
#ifdef TOGL_DLL_EXPORT
|
||||
DLL_EXPORT const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const
|
||||
#else
|
||||
DLL_IMPORT const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const
|
||||
#endif
|
||||
|
||||
const char* GLMDecodeMask( GLMThing_t type, unsigned long value ); // decode a bitmask
|
||||
|
||||
FORCEINLINE void GLMStop( void ) { DXABSTRACT_BREAK_ON_ERROR(); }
|
||||
|
||||
void GLMEnableTrace( bool on );
|
||||
|
||||
//===============================================================================
|
||||
// output functions
|
||||
|
||||
// expose these in release now
|
||||
// Mimic PIX events so we can decorate debug spew
|
||||
DLL_EXPORT void GLMBeginPIXEvent( const char *str );
|
||||
DLL_EXPORT void GLMEndPIXEvent( void );
|
||||
|
||||
class CScopedGLMPIXEvent
|
||||
{
|
||||
CScopedGLMPIXEvent( const CScopedGLMPIXEvent & );
|
||||
CScopedGLMPIXEvent& operator= ( const CScopedGLMPIXEvent & );
|
||||
public:
|
||||
inline CScopedGLMPIXEvent( const char *pName ) { GLMBeginPIXEvent( pName ); }
|
||||
inline ~CScopedGLMPIXEvent() { GLMEndPIXEvent( ); }
|
||||
};
|
||||
|
||||
#if GLMDEBUG
|
||||
|
||||
|
||||
//===============================================================================
|
||||
// classes
|
||||
|
||||
// helper class making function tracking easier to wire up
|
||||
|
||||
class GLMFuncLogger
|
||||
{
|
||||
public:
|
||||
|
||||
// simple function log
|
||||
GLMFuncLogger( const char *funcName )
|
||||
{
|
||||
m_funcName = funcName;
|
||||
m_earlyOut = false;
|
||||
|
||||
GLMPrintf( ">%s", 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( )
|
||||
{
|
||||
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 tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s", __FUNCTION__ )
|
||||
#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;
|
||||
};
|
||||
|
||||
#ifndef OSX
|
||||
void GLMGPUTimestampManagerInit();
|
||||
void GLMGPUTimestampManagerDeinit();
|
||||
void GLMGPUTimestampManagerTick();
|
||||
#endif
|
||||
|
||||
#endif // GLMBASICS_H
|
123
public/togles/linuxwin/glmgrext.h
Normal file
123
public/togles/linuxwin/glmgrext.h
Normal file
@ -0,0 +1,123 @@
|
||||
//========= 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.
|
||||
//
|
||||
// glmgrext.h
|
||||
// helper file for extension testing and runtime importing of entry points
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef OSX
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#elif defined(DX_TO_GL_ABSTRACTION)
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#else
|
||||
#error
|
||||
#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
|
||||
#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
|
||||
|
||||
#ifndef GL_TEXTURE_MINIMIZE_STORAGE_APPLE
|
||||
#define GL_TEXTURE_MINIMIZE_STORAGE_APPLE 0x85B6
|
||||
#endif
|
||||
|
||||
#ifndef GL_ALL_COMPLETED_NV
|
||||
#define GL_ALL_COMPLETED_NV 0x84F2
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAP_READ_BIT
|
||||
#define GL_MAP_READ_BIT 0x0001
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAP_WRITE_BIT
|
||||
#define GL_MAP_WRITE_BIT 0x0002
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAP_INVALIDATE_RANGE_BIT
|
||||
#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAP_INVALIDATE_BUFFER_BIT
|
||||
#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAP_FLUSH_EXPLICIT_BIT
|
||||
#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAP_UNSYNCHRONIZED_BIT
|
||||
#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAP_PERSISTENT_BIT
|
||||
#define GL_MAP_PERSISTENT_BIT 0x0040
|
||||
#endif
|
||||
|
||||
#ifndef GL_MAP_COHERENT_BIT
|
||||
#define GL_MAP_COHERENT_BIT 0x0080
|
||||
#endif
|
||||
|
73
public/togles/rendermechanism.h
Normal file
73
public/togles/rendermechanism.h
Normal file
@ -0,0 +1,73 @@
|
||||
//========= 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.
|
||||
//
|
||||
#ifndef RENDERMECHANISM_H
|
||||
#define RENDERMECHANISM_H
|
||||
|
||||
#if defined(DX_TO_GL_ABSTRACTION)
|
||||
|
||||
#undef PROTECTED_THINGS_ENABLE
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#include "tier0/basetypes.h"
|
||||
#include "tier0/platform.h"
|
||||
|
||||
#include "togl/linuxwin/glmdebug.h"
|
||||
#include "togl/linuxwin/glbase.h"
|
||||
#include "togl/linuxwin/glentrypoints.h"
|
||||
#include "togl/linuxwin/glmdisplay.h"
|
||||
#include "togl/linuxwin/glmdisplaydb.h"
|
||||
#include "togl/linuxwin/glmgrbasics.h"
|
||||
#include "togl/linuxwin/glmgrext.h"
|
||||
#include "togl/linuxwin/cglmbuffer.h"
|
||||
#include "togl/linuxwin/cglmtex.h"
|
||||
#include "togl/linuxwin/cglmfbo.h"
|
||||
#include "togl/linuxwin/cglmprogram.h"
|
||||
#include "togl/linuxwin/cglmquery.h"
|
||||
#include "togl/linuxwin/glmgr.h"
|
||||
#include "togl/linuxwin/dxabstract_types.h"
|
||||
#include "togl/linuxwin/dxabstract.h"
|
||||
|
||||
#else
|
||||
//USE_ACTUAL_DX
|
||||
#ifdef WIN32
|
||||
#ifdef _X360
|
||||
#include "d3d9.h"
|
||||
#include "d3dx9.h"
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include "../../dx9sdk/include/d3d9.h"
|
||||
#include "../../dx9sdk/include/d3dx9.h"
|
||||
#endif
|
||||
typedef HWND VD3DHWND;
|
||||
#endif
|
||||
|
||||
#define GLMPRINTF(args)
|
||||
#define GLMPRINTSTR(args)
|
||||
#define GLMPRINTTEXT(args)
|
||||
#endif // defined(DX_TO_GL_ABSTRACTION)
|
||||
|
||||
#endif // RENDERMECHANISM_H
|
17
togles/linuxwin/asanstubs.cpp
Normal file
17
togles/linuxwin/asanstubs.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
typedef unsigned int uint;
|
||||
|
||||
#include "../public/togl/linuxwin/glmdisplay.h"
|
||||
#include "../public/togl/linuxwin/glmdisplaydb.h"
|
||||
|
||||
void GLMDisplayDB::PopulateRenderers( void ) { }
|
||||
void GLMDisplayDB::PopulateFakeAdapters( uint realRendererIndex ) { } // fake adapters = one real adapter times however many displays are on
|
||||
void GLMDisplayDB::Populate( void ) { }
|
||||
int GLMDisplayDB::GetFakeAdapterCount( void ) { return 1; }
|
||||
bool GLMDisplayDB::GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut ) { return true; }
|
||||
int GLMDisplayDB::GetRendererCount( void ) { return 1; }
|
||||
bool GLMDisplayDB::GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut ) { return true; }
|
||||
int GLMDisplayDB::GetDisplayCount( int rendererIndex ) { return 1; }
|
||||
bool GLMDisplayDB::GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut ) { return true; }
|
||||
int GLMDisplayDB::GetModeCount( int rendererIndex, int displayIndex ) { }
|
||||
bool GLMDisplayDB::GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut ) { return false; }
|
||||
void GLMDisplayDB::Dump( void ) { }
|
1215
togles/linuxwin/cglmbuffer.cpp
Normal file
1215
togles/linuxwin/cglmbuffer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
355
togles/linuxwin/cglmfbo.cpp
Normal file
355
togles/linuxwin/cglmfbo.cpp
Normal file
@ -0,0 +1,355 @@
|
||||
//========= 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.
|
||||
//
|
||||
// cglmfbo.cpp
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#include "togl/rendermechanism.h"
|
||||
|
||||
// memdbgon -must- be the last include file in a .cpp file.
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
CGLMFBO::CGLMFBO( GLMContext *ctx )
|
||||
{
|
||||
m_ctx = ctx;
|
||||
m_ctx->CheckCurrent();
|
||||
|
||||
gGL->glGenFramebuffersEXT( 1, &m_name );
|
||||
|
||||
memset( m_attach, 0, sizeof( m_attach ) );
|
||||
}
|
||||
|
||||
|
||||
CGLMFBO::~CGLMFBO( )
|
||||
{
|
||||
m_ctx->CheckCurrent();
|
||||
|
||||
// detach all known attached textures first... necessary ?
|
||||
for( int index = 0; index < kAttCount; index++)
|
||||
{
|
||||
if (m_attach[ index ].m_tex)
|
||||
{
|
||||
TexDetach( (EGLMFBOAttachment)index );
|
||||
}
|
||||
}
|
||||
|
||||
gGL->glDeleteFramebuffersEXT( 1, &m_name );
|
||||
|
||||
m_name = 0;
|
||||
m_ctx = NULL;
|
||||
}
|
||||
|
||||
// the tex attach path should also select a specific slice of the texture...
|
||||
// and we need a way to make renderbuffers..
|
||||
|
||||
static GLenum EncodeAttachmentFBO( EGLMFBOAttachment index )
|
||||
{
|
||||
if (index < kAttDepth)
|
||||
{
|
||||
return GL_COLOR_ATTACHMENT0_EXT + (int) index;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( index )
|
||||
{
|
||||
case kAttDepth:
|
||||
return GL_DEPTH_ATTACHMENT_EXT;
|
||||
break;
|
||||
|
||||
case kAttStencil:
|
||||
return GL_STENCIL_ATTACHMENT_EXT;
|
||||
break;
|
||||
|
||||
case kAttDepthStencil:
|
||||
return GL_DEPTH_STENCIL_ATTACHMENT_EXT;
|
||||
break;
|
||||
|
||||
default:
|
||||
GLMStop(); // bad news
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GLMStop(); // bad news
|
||||
// shouldn't get here
|
||||
return GL_COLOR_ATTACHMENT0_EXT;
|
||||
}
|
||||
|
||||
void CGLMFBO::TexAttach( GLMFBOTexAttachParams *params, EGLMFBOAttachment attachIndex, GLenum fboBindPoint )
|
||||
{
|
||||
// force our parent context to be current
|
||||
m_ctx->MakeCurrent();
|
||||
|
||||
// bind to context (will cause FBO object creation on first use)
|
||||
m_ctx->BindFBOToCtx( this, fboBindPoint );
|
||||
|
||||
// it's either a plain 2D, a 2D face of a cube map, or a slice of a 3D.
|
||||
CGLMTex *tex = params->m_tex;
|
||||
|
||||
// always detach what is currently there, if anything
|
||||
this->TexDetach( attachIndex, fboBindPoint );
|
||||
|
||||
if (!tex)
|
||||
{
|
||||
// andif they pass NULL to us, then we are done.
|
||||
return;
|
||||
}
|
||||
|
||||
GLMTexLayout *layout = tex->m_layout;
|
||||
|
||||
GLenum target = tex->m_layout->m_key.m_texGLTarget;
|
||||
|
||||
GLenum attachIndexGL = EncodeAttachmentFBO( attachIndex );
|
||||
|
||||
switch( target )
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
{
|
||||
// we will attach the underlying RBO on a multisampled tex, iff the tex has one, **and** we're not being asked to attach it to the read buffer.
|
||||
// if we get a req to attach an MSAA tex to the read buffer, chances are it's BlitTex calling, andit has already resolved the tex, so in those
|
||||
// cases you really do want to attach the texture and not the RBO to the FBO in question.
|
||||
|
||||
bool useRBO = false; // initial state
|
||||
|
||||
if (layout->m_key.m_texFlags & kGLMTexMultisampled)
|
||||
{
|
||||
// it is an MSAA tex
|
||||
if (fboBindPoint == GL_READ_FRAMEBUFFER_EXT)
|
||||
{
|
||||
// I think you just want to read a resolved tex.
|
||||
// But I will check that it is resolved first..
|
||||
Assert( tex->IsRBODirty() == false );
|
||||
}
|
||||
else
|
||||
{
|
||||
// you want to draw into it. You get the RBO bound instead of the tex.
|
||||
useRBO = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (useRBO)
|
||||
{
|
||||
// MSAA path - attach the RBO, not the texture, and mark the RBO dirty
|
||||
if (attachIndexGL==GL_DEPTH_STENCIL_ATTACHMENT_EXT)
|
||||
{
|
||||
// you have to attach it both places...
|
||||
// http://www.opengl.org/wiki/GL_EXT_framebuffer_object
|
||||
|
||||
// bind the RBO to the GL_RENDERBUFFER_EXT target
|
||||
gGL->glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, tex->m_rboName );
|
||||
|
||||
// attach the GL_RENDERBUFFER_EXT target to the depth and stencil attach points
|
||||
gGL->glFramebufferRenderbufferEXT( fboBindPoint, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tex->m_rboName);
|
||||
|
||||
gGL->glFramebufferRenderbufferEXT( fboBindPoint, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tex->m_rboName);
|
||||
|
||||
// no need to leave the RBO hanging on
|
||||
gGL->glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// color attachment (likely 0)
|
||||
gGL->glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, tex->m_rboName );
|
||||
|
||||
gGL->glFramebufferRenderbufferEXT( fboBindPoint, attachIndexGL, GL_RENDERBUFFER_EXT, tex->m_rboName);
|
||||
|
||||
gGL->glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
||||
}
|
||||
tex->ForceRBODirty();
|
||||
}
|
||||
else
|
||||
{
|
||||
// regular path - attaching a texture2d
|
||||
|
||||
if (attachIndexGL==GL_DEPTH_STENCIL_ATTACHMENT_EXT)
|
||||
{
|
||||
// you have to attach it both places...
|
||||
// http://www.opengl.org/wiki/GL_EXT_framebuffer_object
|
||||
|
||||
gGL->glFramebufferTexture2DEXT( fboBindPoint, GL_DEPTH_ATTACHMENT_EXT, target, tex->m_texName, params->m_mip );
|
||||
|
||||
gGL->glFramebufferTexture2DEXT( fboBindPoint, GL_STENCIL_ATTACHMENT_EXT, target, tex->m_texName, params->m_mip );
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL->glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, target, tex->m_texName, params->m_mip );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_3D:
|
||||
{
|
||||
gGL->glFramebufferTexture3DEXT( fboBindPoint, attachIndexGL, target, tex->m_texName, params->m_mip, params->m_zslice );
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
{
|
||||
// adjust target to steer to the proper face of the cube map
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + params->m_face;
|
||||
|
||||
gGL->glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, target, tex->m_texName, params->m_mip );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// log the attached tex
|
||||
m_attach[ attachIndex ] = *params;
|
||||
|
||||
// indicate that the tex has been bound to an RT
|
||||
tex->m_rtAttachCount++;
|
||||
}
|
||||
|
||||
void CGLMFBO::TexDetach( EGLMFBOAttachment attachIndex, GLenum fboBindPoint )
|
||||
{
|
||||
// force our parent context to be current
|
||||
m_ctx->MakeCurrent();
|
||||
|
||||
// bind to context (will cause FBO object creation on first use)
|
||||
m_ctx->BindFBOToCtx( this, fboBindPoint );
|
||||
|
||||
if (m_attach[ attachIndex ].m_tex)
|
||||
{
|
||||
CGLMTex *tex = m_attach[ attachIndex ].m_tex;
|
||||
GLMTexLayout *layout = tex->m_layout;
|
||||
GLenum target = tex->m_layout->m_key.m_texGLTarget;
|
||||
|
||||
GLenum attachIndexGL = EncodeAttachmentFBO( attachIndex );
|
||||
|
||||
switch( target )
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
{
|
||||
if (layout->m_key.m_texFlags & kGLMTexMultisampled)
|
||||
{
|
||||
// MSAA path - detach the RBO, not the texture
|
||||
// (is this the right time to resolve? probably better to wait until someone tries to sample the texture)
|
||||
|
||||
gGL->glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
||||
|
||||
if (attachIndexGL==GL_DEPTH_STENCIL_ATTACHMENT_EXT)
|
||||
{
|
||||
// detach the GL_RENDERBUFFER_EXT target at depth and stencil attach points
|
||||
gGL->glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
|
||||
|
||||
gGL->glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// color attachment (likely 0)
|
||||
gGL->glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachIndexGL, GL_RENDERBUFFER_EXT, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// plain tex detach
|
||||
if (attachIndexGL==GL_DEPTH_STENCIL_ATTACHMENT_EXT)
|
||||
{
|
||||
// you have to detach it both places...
|
||||
// http://www.opengl.org/wiki/GL_EXT_framebuffer_object
|
||||
|
||||
gGL->glFramebufferTexture2DEXT( fboBindPoint, GL_DEPTH_ATTACHMENT_EXT, target, 0, 0 );
|
||||
gGL->glFramebufferTexture2DEXT( fboBindPoint, GL_STENCIL_ATTACHMENT_EXT, target, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL->glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, target, 0, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_3D:
|
||||
{
|
||||
gGL->glFramebufferTexture3DEXT( fboBindPoint, attachIndexGL, target, 0, 0, 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
{
|
||||
gGL->glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, target, 0, 0 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// un-log the attached tex
|
||||
memset( &m_attach[ attachIndex ], 0, sizeof( m_attach[0] ) );
|
||||
|
||||
// drop the RT attach count
|
||||
tex->m_rtAttachCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Debugger(); // odd, but not harmful - typ comes from D3D code passing NULL into SetRenderTarget
|
||||
}
|
||||
}
|
||||
|
||||
void CGLMFBO::TexScrub( CGLMTex *tex )
|
||||
{
|
||||
// see if it's attached anywhere
|
||||
for( int attachIndex = 0; attachIndex < kAttCount; attachIndex++ )
|
||||
{
|
||||
if (m_attach[ attachIndex ].m_tex == tex)
|
||||
{
|
||||
// blammo
|
||||
TexDetach( (EGLMFBOAttachment)attachIndex, GL_DRAW_FRAMEBUFFER_EXT );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CGLMFBO::IsReady( void )
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// ensure our parent context is current
|
||||
m_ctx->CheckCurrent();
|
||||
|
||||
// bind to context (will cause FBO object creation on first use)
|
||||
m_ctx->BindFBOToCtx( this );
|
||||
|
||||
GLenum status;
|
||||
status = gGL->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
switch(status)
|
||||
{
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
result = false;
|
||||
DebuggerBreak();
|
||||
/* choose different formats */
|
||||
break;
|
||||
|
||||
default:
|
||||
result = false;
|
||||
DebuggerBreak();
|
||||
/* programming error; will fail on all hardware */
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
1570
togles/linuxwin/cglmprogram.cpp
Normal file
1570
togles/linuxwin/cglmprogram.cpp
Normal file
File diff suppressed because it is too large
Load Diff
363
togles/linuxwin/cglmquery.cpp
Normal file
363
togles/linuxwin/cglmquery.cpp
Normal file
@ -0,0 +1,363 @@
|
||||
//========= 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.
|
||||
//
|
||||
// cglmquery.cpp
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#include "togl/rendermechanism.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
// memdbgon -must- be the last include file in a .cpp file.
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// http://www.opengl.org/registry/specs/ARB/occlusion_query.txt
|
||||
// Workaround for "Calling either GenQueriesARB or DeleteQueriesARB while any query of any target is active causes an INVALID_OPERATION error to be generated."
|
||||
uint CGLMQuery::s_nTotalOcclusionQueryCreatesOrDeletes;
|
||||
|
||||
extern ConVar gl_errorcheckall;
|
||||
extern ConVar gl_errorcheckqueries;
|
||||
extern ConVar gl_errorchecknone;
|
||||
|
||||
// how many microseconds to wait after a failed query-available test
|
||||
// presently on MTGL this doesn't happen, but it could change, keep this handy
|
||||
ConVar gl_nullqueries( "gl_nullqueries", "0" );
|
||||
|
||||
|
||||
//===============================================================================
|
||||
|
||||
CGLMQuery::CGLMQuery( GLMContext *ctx, GLMQueryParams *params )
|
||||
{
|
||||
// get the type of query requested
|
||||
// generate name(s) needed
|
||||
// set initial state appropriately
|
||||
|
||||
m_ctx = ctx;
|
||||
m_params = *params;
|
||||
|
||||
m_name = 0;
|
||||
m_syncobj = 0;
|
||||
|
||||
m_started = m_stopped = m_done = false;
|
||||
|
||||
m_nullQuery = false;
|
||||
// assume value of convar at start time
|
||||
// does not change during individual query lifetime
|
||||
// started null = stays null
|
||||
// started live = stays live
|
||||
|
||||
switch(m_params.m_type)
|
||||
{
|
||||
case EOcclusion:
|
||||
{
|
||||
//make an occlusion query (and a fence to go with it)
|
||||
gGL->glGenQueriesARB( 1, &m_name );
|
||||
s_nTotalOcclusionQueryCreatesOrDeletes++;
|
||||
GLMPRINTF(("-A- CGLMQuery(OQ) created name %d", m_name));
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
//make a fence - no aux fence needed
|
||||
|
||||
m_syncobj = 0;
|
||||
|
||||
if (gGL->m_bHave_GL_ARB_sync)
|
||||
{ /* GL_ARB_sync doesn't separate gen and set, so we do glFenceSync() later. */ }
|
||||
else if (gGL->m_bHave_GL_NV_fence)
|
||||
gGL->glGenFencesNV(1, &m_name );
|
||||
else if (gGL->m_bHave_GL_APPLE_fence)
|
||||
gGL->glGenFencesAPPLE(1, &m_name );
|
||||
|
||||
GLMPRINTF(("-A- CGLMQuery(fence) created name %d", m_name));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CGLMQuery::~CGLMQuery()
|
||||
{
|
||||
GLMPRINTF(("-A-> ~CGLMQuery"));
|
||||
|
||||
// make sure query has completed (might not be necessary)
|
||||
// delete the name(s)
|
||||
|
||||
switch(m_params.m_type)
|
||||
{
|
||||
case EOcclusion:
|
||||
{
|
||||
// do a finish occlusion query ?
|
||||
GLMPRINTF(("-A- ~CGLMQuery(OQ) deleting name %d", m_name));
|
||||
gGL->glDeleteQueriesARB(1, &m_name );
|
||||
s_nTotalOcclusionQueryCreatesOrDeletes++;
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
{
|
||||
// do a finish fence ?
|
||||
GLMPRINTF(("-A- ~CGLMQuery(fence) deleting name %llu", gGL->m_bHave_GL_ARB_sync ? (unsigned long long) m_syncobj : (unsigned long long) m_name));
|
||||
#ifdef HAVE_GL_ARB_SYNC
|
||||
if (gGL->m_bHave_GL_ARB_sync)
|
||||
gGL->glDeleteSync( m_syncobj );
|
||||
else
|
||||
#endif
|
||||
if (gGL->m_bHave_GL_NV_fence)
|
||||
gGL->glDeleteFencesNV(1, &m_name );
|
||||
else if (gGL->m_bHave_GL_APPLE_fence)
|
||||
gGL->glDeleteFencesAPPLE(1, &m_name );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_name = 0;
|
||||
m_syncobj = 0;
|
||||
|
||||
GLMPRINTF(("-A-< ~CGLMQuery"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void CGLMQuery::Start( void ) // "start counting"
|
||||
{
|
||||
m_nullQuery = (gl_nullqueries.GetInt() != 0); // latch value for remainder of query life
|
||||
|
||||
m_started = true;
|
||||
m_stopped = false;
|
||||
m_done = false;
|
||||
|
||||
switch(m_params.m_type)
|
||||
{
|
||||
case EOcclusion:
|
||||
{
|
||||
if (m_nullQuery)
|
||||
{
|
||||
// do nothing..
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL->glBeginQueryARB( GL_SAMPLES_PASSED_ARB, m_name );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
#ifdef HAVE_GL_ARB_SYNC
|
||||
if (gGL->m_bHave_GL_ARB_sync)
|
||||
{
|
||||
if (m_syncobj != 0) gGL->glDeleteSync(m_syncobj);
|
||||
m_syncobj = gGL->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (gGL->m_bHave_GL_NV_fence)
|
||||
gGL->glSetFenceNV( m_name, GL_ALL_COMPLETED_NV );
|
||||
else if (gGL->m_bHave_GL_APPLE_fence)
|
||||
gGL->glSetFenceAPPLE( m_name );
|
||||
|
||||
m_stopped = true; // caller should not call Stop on a fence, it self-stops
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CGLMQuery::Stop( void ) // "stop counting"
|
||||
{
|
||||
Assert(m_started);
|
||||
|
||||
if ( m_stopped )
|
||||
return;
|
||||
|
||||
switch(m_params.m_type)
|
||||
{
|
||||
case EOcclusion:
|
||||
{
|
||||
if (m_nullQuery)
|
||||
{
|
||||
// do nothing..
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL->glEndQueryARB( GL_SAMPLES_PASSED_ARB ); // we are only putting the request-to-stop-counting into the cmd stream.
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
// nop - you don't "end" a fence, you just test it and/or finish it out in Complete
|
||||
break;
|
||||
}
|
||||
|
||||
m_stopped = true;
|
||||
}
|
||||
|
||||
bool CGLMQuery::IsDone( void )
|
||||
{
|
||||
Assert(m_started);
|
||||
Assert(m_stopped);
|
||||
|
||||
if(!m_done) // you can ask more than once, but we only check until it comes back as done.
|
||||
{
|
||||
// on occlusion: glGetQueryObjectivARB - large cost on pre SLGU, cheap after
|
||||
// on fence: glTestFence* on the fence
|
||||
switch(m_params.m_type)
|
||||
{
|
||||
case EOcclusion: // just test the fence that was set after the query begin
|
||||
{
|
||||
if (m_nullQuery)
|
||||
{
|
||||
// do almost nothing.. but claim work is complete
|
||||
m_done = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// prepare to pay a big price on drivers prior to 10.6.4+SLGU
|
||||
|
||||
GLint available = 0;
|
||||
gGL->glGetQueryObjectivARB(m_name, GL_QUERY_RESULT_AVAILABLE_ARB, &available );
|
||||
|
||||
m_done = (available != 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
{
|
||||
#ifdef HAVE_GL_ARB_SYNC
|
||||
if (gGL->m_bHave_GL_ARB_sync)
|
||||
m_done = (gGL->glClientWaitSync( m_syncobj, 0, 0 ) == GL_ALREADY_SIGNALED);
|
||||
else
|
||||
#endif
|
||||
if ( m_name == 0 )
|
||||
m_done = true;
|
||||
else if (gGL->m_bHave_GL_NV_fence)
|
||||
m_done = gGL->glTestFenceNV( m_name ) != 0;
|
||||
else if (gGL->m_bHave_GL_APPLE_fence)
|
||||
m_done = gGL->glTestFenceAPPLE( m_name ) != 0;
|
||||
|
||||
if (m_done)
|
||||
{
|
||||
if (gGL->m_bHave_GL_ARB_sync)
|
||||
{ /* no-op; we already know it's set to GL_ALREADY_SIGNALED. */ }
|
||||
else
|
||||
{
|
||||
if (gGL->m_bHave_GL_NV_fence)
|
||||
gGL->glFinishFenceNV( m_name ); // no set fence goes un-finished
|
||||
else if (gGL->m_bHave_GL_APPLE_fence)
|
||||
gGL->glFinishFenceAPPLE( m_name ); // no set fence goes un-finished
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return m_done;
|
||||
}
|
||||
|
||||
void CGLMQuery::Complete( uint *result )
|
||||
{
|
||||
uint resultval = 0;
|
||||
//bool bogus_available = false;
|
||||
|
||||
// blocking call if not done
|
||||
Assert(m_started);
|
||||
Assert(m_stopped);
|
||||
|
||||
switch(m_params.m_type)
|
||||
{
|
||||
case EOcclusion:
|
||||
{
|
||||
if (m_nullQuery)
|
||||
{
|
||||
m_done = true;
|
||||
resultval = 0; // we did say "null queries..."
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL->glGetQueryObjectuivARB( m_name, GL_QUERY_RESULT_ARB, &resultval);
|
||||
m_done = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
{
|
||||
if(!m_done)
|
||||
{
|
||||
#ifdef HAVE_GL_ARB_SYNC
|
||||
if (gGL->m_bHave_GL_ARB_sync)
|
||||
{
|
||||
if (gGL->glClientWaitSync( m_syncobj, 0, 0 ) != GL_ALREADY_SIGNALED)
|
||||
{
|
||||
GLenum syncstate;
|
||||
do {
|
||||
const GLuint64 timeout = 10 * ((GLuint64)1000 * 1000 * 1000); // 10 seconds in nanoseconds.
|
||||
(void)timeout;
|
||||
syncstate = gGL->glClientWaitSync( m_syncobj, GL_SYNC_FLUSH_COMMANDS_BIT, 0 );
|
||||
} while (syncstate == GL_TIMEOUT_EXPIRED); // any errors or success break out of this loop.
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (gGL->m_bHave_GL_NV_fence)
|
||||
gGL->glFinishFenceNV( m_name );
|
||||
else if (gGL->m_bHave_GL_APPLE_fence)
|
||||
gGL->glFinishFenceAPPLE( m_name );
|
||||
|
||||
m_done = true; // for clarity or if they try to Complete twice
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Assert( m_done );
|
||||
|
||||
// reset state for re-use - i.e. you have to call Complete if you want to re-use the object
|
||||
m_started = m_stopped = m_done = false;
|
||||
|
||||
if (result) // caller may pass NULL if not interested in result, for example to clear a fence
|
||||
{
|
||||
*result = resultval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// accessors for the started/stopped state
|
||||
bool CGLMQuery::IsStarted ( void )
|
||||
{
|
||||
return m_started;
|
||||
}
|
||||
|
||||
bool CGLMQuery::IsStopped ( void )
|
||||
{
|
||||
return m_stopped;
|
||||
}
|
||||
|
1990
togles/linuxwin/cglmtex.cpp
Normal file
1990
togles/linuxwin/cglmtex.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3838
togles/linuxwin/dx9asmtogl2.cpp
Normal file
3838
togles/linuxwin/dx9asmtogl2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
261
togles/linuxwin/dx9asmtogl2.h
Normal file
261
togles/linuxwin/dx9asmtogl2.h
Normal file
@ -0,0 +1,261 @@
|
||||
//========= 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.
|
||||
//------------------------------------------------------------------------------
|
||||
// DX9AsmToGL2.h
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef DX9_ASM_TO_GL_2_H
|
||||
#define DX9_ASM_TO_GL_2_H
|
||||
#include "tier1/utlstring.h"
|
||||
|
||||
#define DISASM_OK 0
|
||||
#define DISASM_ERROR 1
|
||||
|
||||
#define MAX_SHADER_CONSTANTS 512
|
||||
|
||||
#define MAX_DECLARED_OUTPUTS 32
|
||||
#define MAX_DECLARED_INPUTS 32
|
||||
|
||||
#define HEXCODE_HEADER "// Hex: "
|
||||
|
||||
// Option bits
|
||||
#define D3DToGL_OptionUseEnvParams 0x0001
|
||||
#define D3DToGL_OptionDoFixupZ 0x0002 // Add instructions to put Z in the right interval for GL
|
||||
#define D3DToGL_OptionDoFixupY 0x0004 // Add instructions to flip the Y over for GL
|
||||
#define D3DToGL_OptionDoUserClipPlanes 0x0008 // ARB mode: Include OPTION vertex_program_2 and append DP4's to write into oCLP[0] and oCLP[1]
|
||||
// GLSL mode: generate code to write gl_ClipVertex
|
||||
|
||||
#define D3DToGL_AddHexComments 0x0020 // Include hex comments in the code for debugging
|
||||
#define D3DToGL_PutHexCommentsAfterLines 0x0040 // If D3DToGL_AddHexComments is set, this puts the codes to the right, rather than on separate lines
|
||||
#define D3DToGL_GeneratingDebugText 0x0080 // This tells it that we're just getting info for debugging so go easy on asserts and errors
|
||||
#define D3DToGL_OptionSRGBWriteSuffix 0x0400 // Tack sRGB conversion suffix on to pixel shaders
|
||||
#define D3DToGL_OptionGenerateBoneUniformBuffer 0x0800 // if enabled, the vertex shader "bone" registers (all regs DXABSTRACT_VS_FIRST_BONE_SLOT and higher) will be separated out into another uniform buffer (vcbone)
|
||||
#define D3DToGL_OptionUseBindlessTexturing 0x1000
|
||||
#define D3DToGL_OptionSpew 0x80000000
|
||||
|
||||
// Code for which component of the "dummy" address register is needed by an instruction
|
||||
#define ARL_DEST_NONE -1
|
||||
#define ARL_DEST_X 0
|
||||
#define ARL_DEST_Y 1
|
||||
#define ARL_DEST_Z 2
|
||||
#define ARL_DEST_W 3
|
||||
|
||||
class D3DToGL
|
||||
{
|
||||
private:
|
||||
// Pointers for dwToken stream management
|
||||
uint32* m_pdwBaseToken;
|
||||
uint32* m_pdwNextToken;
|
||||
|
||||
// Vertex shader or pixel shader, and version (necessary because some opcodes alias)
|
||||
bool m_bVertexShader;
|
||||
uint32 m_dwMinorVersion;
|
||||
uint32 m_dwMajorVersion;
|
||||
|
||||
// Option flags
|
||||
bool m_bUseEnvParams; // set D3DToGL_OptionUseEnvParams in 'options' to use
|
||||
bool m_bDoFixupZ; // set D3DToGL_OptionDoFixupZ
|
||||
bool m_bDoFixupY; // set D3DToGL_OptionDoFixupZ
|
||||
bool m_bDoUserClipPlanes; // set D3DToGL_OptionDoUserClipPlanes
|
||||
bool m_bSpew; // set D3DToGL_OptionSpew
|
||||
bool m_bGenerateSRGBWriteSuffix; // set D3DToGL_OptionSRGBWriteSuffix
|
||||
bool m_bGenerateBoneUniformBuffer;
|
||||
bool m_bUseBindlessTexturing;
|
||||
|
||||
// Counter for dealing with nested loops
|
||||
int m_nLoopDepth;
|
||||
|
||||
// Add "// Hex: 0xFFEEF00"-type statements after each instruction is parsed.
|
||||
bool m_bAddHexCodeComments; // set D3DToGL_AddHexComments
|
||||
|
||||
// Only applicable if m_bAddHexCodeComments is true.
|
||||
// If this is true, then it puts the hex code comments to the right of the instructions in a comment
|
||||
// rather than preceding the instructions.
|
||||
// Defaults to FALSE.
|
||||
bool m_bPutHexCodesAfterLines; // set D3DToGL_PutHexCommentsAtEnd
|
||||
|
||||
// This tells it that we're just getting info for debugging so go easy on asserts and errors.
|
||||
// Defaults to FALSE.
|
||||
bool m_bGeneratingDebugText;
|
||||
|
||||
// Various scratch temps needed to handle mis-matches in instruction sets between D3D and OpenGL
|
||||
bool m_bNeedsD2AddTemp;
|
||||
bool m_bNeedsNRMTemp;
|
||||
bool m_bDeclareAddressReg;
|
||||
bool m_bNeedsLerpTemp;
|
||||
bool m_bNeedsSinCosDeclarations;
|
||||
|
||||
// Keep track of which vs outputs are used so we can declare them
|
||||
bool m_bDeclareVSOPos;
|
||||
bool m_bDeclareVSOFog;
|
||||
uint32 m_dwTexCoordOutMask;
|
||||
|
||||
int32 m_nVSPositionOutput;
|
||||
|
||||
// Mask of varyings which need centroid decoration
|
||||
uint32 m_nCentroidMask;
|
||||
|
||||
// Keep track of which temps are used so they can be declared
|
||||
uint32 m_dwTempUsageMask;
|
||||
uint32 m_dwTempBoolUsageMask;
|
||||
bool m_bOutputColorRegister[4];
|
||||
bool m_bOutputDepthRegister;
|
||||
|
||||
// Declaration of integer and bool constants
|
||||
uint32 m_dwConstIntUsageMask;
|
||||
uint32 m_dwConstBoolUsageMask;
|
||||
|
||||
uint32 m_dwDefConstIntUsageMask;
|
||||
uint32 m_dwDefConstIntIterCount[32];
|
||||
|
||||
// Did we use atomic_temp_var?
|
||||
bool m_bUsedAtomicTempVar;
|
||||
|
||||
// Track constants so we know how to declare them
|
||||
bool m_bConstantRegisterDefined[MAX_SHADER_CONSTANTS];
|
||||
|
||||
// Track sampler types when declared so we can properly decorate TEX instructions
|
||||
uint32 m_dwSamplerTypes[32];
|
||||
|
||||
// Track sampler usage
|
||||
uint32 m_dwSamplerUsageMask;
|
||||
|
||||
// Track shadow sampler usage
|
||||
int m_nShadowDepthSamplerMask;
|
||||
bool m_bDeclareShadowOption;
|
||||
|
||||
// Track attribute references
|
||||
// init to 0xFFFFFFFF (unhit)
|
||||
// index by (dwRegToken & D3DSP_REGNUM_MASK) in VS DCL insns
|
||||
// fill with (usage<<4) | (usage index).
|
||||
uint32 m_dwAttribMap[16];
|
||||
|
||||
// Register high water mark
|
||||
uint32 m_nHighestRegister;
|
||||
int32 m_nHighestBoneRegister;
|
||||
|
||||
// GLSL does indentation for readability
|
||||
int m_NumIndentTabs;
|
||||
|
||||
// Output buffers.
|
||||
CUtlBuffer *m_pBufHeaderCode;
|
||||
CUtlBuffer *m_pBufAttribCode;
|
||||
CUtlBuffer *m_pBufParamCode;
|
||||
CUtlBuffer *m_pBufALUCode;
|
||||
|
||||
char *m_pFinalAssignmentsCode;
|
||||
int m_nFinalAssignmentsBufSize;
|
||||
|
||||
// Recorded positions for debugging.
|
||||
uint32* m_pRecordedInputTokenStart;
|
||||
int m_nRecordedParamCodeStrlen;
|
||||
int m_nRecordedALUCodeStrlen;
|
||||
int m_nRecordedAttribCodeStrlen;
|
||||
|
||||
// In GLSL mode, these store the semantic attached to each oN register.
|
||||
// They are the values that you pass to GetUsageIndexAndString.
|
||||
uint32 m_DeclaredOutputs[MAX_DECLARED_OUTPUTS];
|
||||
|
||||
uint32 m_DeclaredInputs[MAX_DECLARED_INPUTS];
|
||||
|
||||
// Have they used the tangent input semantic (i.e. is g_pTangentAttributeName declared)?
|
||||
bool m_bTangentInputUsed;
|
||||
|
||||
bool m_bUsesDSTInstruction;
|
||||
|
||||
private:
|
||||
// Utilities to aid in decoding token stream
|
||||
uint32 GetNextToken( void );
|
||||
void SkipTokens( uint32 numToSkip );
|
||||
uint32 Opcode( uint32 dwToken );
|
||||
uint32 OpcodeSpecificData( uint32 dwToken );
|
||||
uint32 TextureType ( uint32 dwToken );
|
||||
uint32 GetRegType( uint32 dwRegToken );
|
||||
|
||||
// Write to the different buffers.
|
||||
void StrcatToHeaderCode( const char *pBuf );
|
||||
void StrcatToALUCode( const char *pBuf );
|
||||
void StrcatToParamCode( const char *pBuf );
|
||||
void StrcatToAttribCode( const char *pBuf );
|
||||
void PrintToBufWithIndents( CUtlBuffer &buf, const char *pFormat, ... );
|
||||
|
||||
// This helps write the token hex codes into the output stream for debugging.
|
||||
void AddTokenHexCodeToBuffer( char *pBuffer, int nSize, int nLastStrlen );
|
||||
void RecordInputAndOutputPositions();
|
||||
void AddTokenHexCode();
|
||||
|
||||
// Utilities for decoding tokens in to strings according to ASM syntax
|
||||
void PrintOpcode( uint32 inst, char* buff, int nBufLen );
|
||||
|
||||
// fSemanticFlags is SEMANTIC_INPUT or SEMANTIC_OUTPUT.
|
||||
void PrintUsageAndIndexToString( uint32 dwToken, char* strUsageUsageIndexName, int nBufLen, int fSemanticFlags );
|
||||
CUtlString GetUsageAndIndexString( uint32 dwToken, int fSemanticFlags );
|
||||
CUtlString GetParameterString( uint32 dwToken, uint32 dwSourceOrDest, bool bForceScalarSource, int *pARLDestReg );
|
||||
const char* GetGLSLOperatorString( uint32 inst );
|
||||
|
||||
void PrintParameterToString ( uint32 dwToken, uint32 dwSourceOrDest, char *pRegisterName, int nBufLen, bool bForceScalarSource, int *pARLDestReg );
|
||||
|
||||
void InsertMoveFromAddressRegister( CUtlBuffer *pCode, int nARLComp0, int nARLComp1, int nARLComp2 = ARL_DEST_NONE );
|
||||
void InsertMoveInstruction( CUtlBuffer *pCode, int nARLComponent );
|
||||
void FlagIndirectRegister( uint32 dwToken, int *pARLDestReg );
|
||||
|
||||
// Utilities for decoding tokens in to strings according to GLSL syntax
|
||||
bool OpenIntrinsic( uint32 inst, char* buff, int nBufLen, uint32 destDimension, uint32 nArgumentDimension );
|
||||
void PrintIndentation( char *pBuf, int nBufLen );
|
||||
|
||||
uint32 MaintainAttributeMap( uint32 dwToken, uint32 dwRegToken );
|
||||
|
||||
CUtlString FixGLSLSwizzle( const char *pDestRegisterName, const char *pSrcRegisterName );
|
||||
void WriteGLSLCmp( const char *pDestReg, const char *pSrc0Reg, const char *pSrc1Reg, const char *pSrc2Reg );
|
||||
void WriteGLSLSamplerDefinitions();
|
||||
void WriteGLSLOutputVariableAssignments();
|
||||
void WriteGLSLInputVariableAssignments();
|
||||
void NoteTangentInputUsed();
|
||||
|
||||
void Handle_DCL();
|
||||
void Handle_DEF();
|
||||
void Handle_DEFIB( uint32 nInstruction );
|
||||
void Handle_MAD( uint32 nInstruction );
|
||||
void Handle_DP2ADD();
|
||||
void Handle_SINCOS();
|
||||
void Handle_LRP( uint32 nInstruction );
|
||||
void Handle_TEX( uint32 dwToken, bool bIsTexLDL );
|
||||
void Handle_TexLDD( uint32 nInstruction );
|
||||
void Handle_TexCoord();
|
||||
void Handle_UnaryOp( uint32 nInstruction );
|
||||
void Handle_BREAKC( uint32 dwToken );
|
||||
void HandleBinaryOp_GLSL( uint32 nInstruction );
|
||||
void HandleBinaryOp_ASM( uint32 nInstruction );
|
||||
void Handle_CMP();
|
||||
void Handle_NRM();
|
||||
void Handle_DeclarativeNonDclOp( uint32 nInstruction );
|
||||
|
||||
public:
|
||||
D3DToGL();
|
||||
|
||||
int TranslateShader( uint32* code, CUtlBuffer *pBufDisassembledCode, bool *bVertexShader, uint32 options, int32 nShadowDepthSamplerMask, uint32 nCentroidMask, char *debugLabel );
|
||||
};
|
||||
|
||||
|
||||
#endif // DX9_ASM_TO_GL_2_H
|
6845
togles/linuxwin/dxabstract.cpp
Normal file
6845
togles/linuxwin/dxabstract.cpp
Normal file
File diff suppressed because it is too large
Load Diff
512
togles/linuxwin/glentrypoints.cpp
Normal file
512
togles/linuxwin/glentrypoints.cpp
Normal file
@ -0,0 +1,512 @@
|
||||
//========= 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.
|
||||
//
|
||||
// glentrypoints.cpp
|
||||
//
|
||||
//=============================================================================//
|
||||
// Immediately include gl.h, etc. here to avoid compilation warnings.
|
||||
|
||||
#include "togl/rendermechanism.h"
|
||||
|
||||
#include "appframework/AppFramework.h"
|
||||
#include "appframework/IAppSystemGroup.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/icommandline.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "interface.h"
|
||||
#include "filesystem.h"
|
||||
#include "filesystem_init.h"
|
||||
#include "tier1/convar.h"
|
||||
#include "vstdlib/cvar.h"
|
||||
#include "inputsystem/ButtonCode.h"
|
||||
#include "tier1.h"
|
||||
#include "tier2/tier2.h"
|
||||
|
||||
#if defined(_LINUX) && !defined(__ANDROID__)
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
|
||||
// NOTE: This has to be the last file included!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#if !defined(DX_TO_GL_ABSTRACTION)
|
||||
#error
|
||||
#endif
|
||||
|
||||
#if defined(OSX) || defined(LINUX) || (defined (WIN32) && defined( DX_TO_GL_ABSTRACTION ))
|
||||
#include "appframework/ilaunchermgr.h"
|
||||
ILauncherMgr *g_pLauncherMgr = NULL;
|
||||
#endif
|
||||
|
||||
#define DEBUG_ALL_GLCALLS 0
|
||||
|
||||
#if DEBUG_ALL_GLCALLS
|
||||
bool g_bDebugOpenGLCalls = true;
|
||||
bool g_bPrintOpenGLCalls = false;
|
||||
|
||||
#define GL_EXT(x,glmajor,glminor)
|
||||
#define GL_FUNC(ext,req,ret,fn,arg,call) \
|
||||
static ret (*fn##_gldebugptr) arg = NULL; \
|
||||
static ret fn##_gldebug arg { \
|
||||
if (!g_bDebugOpenGLCalls) { return fn##_gldebugptr call; } \
|
||||
if (g_bPrintOpenGLCalls) { \
|
||||
printf("Calling %s ... ", #fn); \
|
||||
fflush(stdout); \
|
||||
} \
|
||||
ret retval = fn##_gldebugptr call; \
|
||||
if (g_bPrintOpenGLCalls) { \
|
||||
printf("%s returned!\n", #fn); \
|
||||
fflush(stdout); \
|
||||
} \
|
||||
const GLenum err = glGetError_gldebugptr(); \
|
||||
if ( err == GL_INVALID_FRAMEBUFFER_OPERATION_EXT ) { \
|
||||
const GLenum fberr = gGL->glCheckFramebufferStatus( GL_FRAMEBUFFER_EXT ); \
|
||||
printf("%s triggered error GL_INVALID_FRAMEBUFFER_OPERATION_EXT! (0x%X)\n\n\n", #fn, (int) fberr); \
|
||||
fflush(stdout); \
|
||||
__asm__ __volatile__ ( "int $3\n\t" ); \
|
||||
} else if (err != GL_NO_ERROR) { \
|
||||
printf("%s triggered error 0x%X!\n\n\n", #fn, (int) err); \
|
||||
fflush(stdout); \
|
||||
__asm__ __volatile__ ( "int $3\n\t" ); \
|
||||
} \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
#define GL_FUNC_VOID(ext,req,fn,arg,call) \
|
||||
static void (*fn##_gldebugptr) arg = NULL; \
|
||||
static void fn##_gldebug arg { \
|
||||
if (!g_bDebugOpenGLCalls) { fn##_gldebugptr call; return; } \
|
||||
if (g_bPrintOpenGLCalls) { \
|
||||
printf("Calling %s ... ", #fn); \
|
||||
fflush(stdout); \
|
||||
} \
|
||||
fn##_gldebugptr call; \
|
||||
if (g_bPrintOpenGLCalls) { \
|
||||
printf("%s returned!\n", #fn); \
|
||||
fflush(stdout); \
|
||||
} \
|
||||
const GLenum err = glGetError_gldebugptr(); \
|
||||
if ( err == GL_INVALID_FRAMEBUFFER_OPERATION_EXT ) { \
|
||||
const GLenum fberr = gGL->glCheckFramebufferStatus( GL_FRAMEBUFFER_EXT ); \
|
||||
printf("%s triggered error GL_INVALID_FRAMEBUFFER_OPERATION_EXT! (0x%X)\n\n\n", #fn, (int) fberr); \
|
||||
fflush(stdout); \
|
||||
__asm__ __volatile__ ( "int $3\n\t" ); \
|
||||
} else if (err != GL_NO_ERROR) { \
|
||||
printf("%s triggered error 0x%X!\n\n\n", #fn, (int) err); \
|
||||
fflush(stdout); \
|
||||
__asm__ __volatile__ ( "int $3\n\t" ); \
|
||||
} \
|
||||
}
|
||||
|
||||
#include "togl/glfuncs.inl"
|
||||
#undef GL_FUNC_VOID
|
||||
#undef GL_FUNC
|
||||
#undef GL_EXT
|
||||
#endif
|
||||
|
||||
COpenGLEntryPoints *gGL = NULL;
|
||||
GL_GetProcAddressCallbackFunc_t gGL_GetProcAddressCallback = NULL;
|
||||
|
||||
void *VoidFnPtrLookup_GlMgr(const char *fn, bool &okay, const bool bRequired, void *fallback)
|
||||
{
|
||||
void *retval = NULL;
|
||||
if ((!okay) && (!bRequired)) // always look up if required (so we get a complete list of crucial missing symbols).
|
||||
return NULL;
|
||||
|
||||
// SDL does the right thing, so we never need to use tier0 in this case.
|
||||
retval = (*gGL_GetProcAddressCallback)(fn, okay, bRequired, fallback);
|
||||
//printf("CDynamicFunctionOpenGL: SDL_GL_GetProcAddress(\"%s\") returned %p\n", fn, retval);
|
||||
if ((retval == NULL) && (fallback != NULL))
|
||||
{
|
||||
//printf("CDynamicFunctionOpenGL: Using fallback %p for \"%s\"\n", fallback, fn);
|
||||
retval = fallback;
|
||||
}
|
||||
|
||||
// Note that a non-NULL response doesn't mean it's safe to call the function!
|
||||
// You always have to check that the extension is supported;
|
||||
// an implementation MAY return NULL in this case, but it doesn't have to (and doesn't, with the DRI drivers).
|
||||
okay = (okay && (retval != NULL));
|
||||
if (bRequired && !okay)
|
||||
fprintf(stderr, "Could not find required OpenGL entry point '%s'!\n", fn);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback)
|
||||
{
|
||||
if (gGL == NULL)
|
||||
{
|
||||
gGL_GetProcAddressCallback = callback;
|
||||
gGL = new COpenGLEntryPoints();
|
||||
if (!gGL->m_bHave_OpenGL)
|
||||
Error( "Missing basic required OpenGL functionality." );
|
||||
|
||||
}
|
||||
return gGL;
|
||||
}
|
||||
|
||||
void ClearOpenGLEntryPoints()
|
||||
{
|
||||
if ( gGL )
|
||||
{
|
||||
gGL->ClearEntryPoints();
|
||||
}
|
||||
}
|
||||
COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory )
|
||||
{
|
||||
ConnectTier1Libraries( &factory, 1 );
|
||||
ConVar_Register();
|
||||
ConnectTier2Libraries( &factory, 1 );
|
||||
|
||||
if ( !g_pFullFileSystem )
|
||||
{
|
||||
Warning( "ToGL was unable to access the required interfaces!\n" );
|
||||
}
|
||||
|
||||
// NOTE! : Overbright is 1.0 so that Hammer will work properly with the white bumped and unbumped lightmaps.
|
||||
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
|
||||
|
||||
#if defined( USE_SDL )
|
||||
g_pLauncherMgr = (ILauncherMgr *)factory( SDLMGR_INTERFACE_VERSION, NULL );
|
||||
#endif
|
||||
|
||||
return gGL;
|
||||
}
|
||||
|
||||
void ToGLDisconnectLibraries()
|
||||
{
|
||||
DisconnectTier2Libraries();
|
||||
ConVar_Unregister();
|
||||
DisconnectTier1Libraries();
|
||||
}
|
||||
|
||||
#define GLVERNUM(Major, Minor, Patch) (((Major) * 100000) + ((Minor) * 1000) + (Patch))
|
||||
|
||||
static void GetOpenGLVersion(int *major, int *minor, int *patch)
|
||||
{
|
||||
*major = *minor = *patch = 0;
|
||||
static CDynamicFunctionOpenGL< true, const GLubyte *( APIENTRY *)(GLenum name), const GLubyte * > glGetString("glGetString");
|
||||
if (glGetString)
|
||||
{
|
||||
const char *version = (const char *) glGetString(GL_VERSION);
|
||||
if (version)
|
||||
{
|
||||
sscanf( version, "%d.%d.%d", major, minor, patch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int GetOpenGLVersionMajor()
|
||||
{
|
||||
int major, minor, patch;
|
||||
GetOpenGLVersion(&major, &minor, &patch);
|
||||
return major;
|
||||
}
|
||||
|
||||
static int GetOpenGLVersionMinor()
|
||||
{
|
||||
int major, minor, patch;
|
||||
GetOpenGLVersion(&major, &minor, &patch);
|
||||
return minor;
|
||||
}
|
||||
|
||||
static int GetOpenGLVersionPatch()
|
||||
{
|
||||
int major, minor, patch;
|
||||
GetOpenGLVersion(&major, &minor, &patch);
|
||||
return patch;
|
||||
}
|
||||
|
||||
static bool CheckBaseOpenGLVersion()
|
||||
{
|
||||
const int NEED_MAJOR = 2;
|
||||
const int NEED_MINOR = 0;
|
||||
const int NEED_PATCH = 0;
|
||||
|
||||
int major, minor, patch;
|
||||
GetOpenGLVersion(&major, &minor, &patch);
|
||||
|
||||
const int need = GLVERNUM(NEED_MAJOR, NEED_MINOR, NEED_PATCH);
|
||||
const int have = GLVERNUM(major, minor, patch);
|
||||
if (have < need)
|
||||
{
|
||||
fprintf(stderr, "PROBLEM: You appear to have OpenGL %d.%d.%d, but we need at least %d.%d.%d!\n",
|
||||
major, minor, patch, NEED_MAJOR, NEED_MINOR, NEED_PATCH);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CheckOpenGLExtension_internal(const char *ext, const int coremajor, const int coreminor)
|
||||
{
|
||||
if ((coremajor >= 0) && (coreminor >= 0)) // we know that this extension is part of the base spec as of GL_VERSION coremajor.coreminor.
|
||||
{
|
||||
int major, minor, patch;
|
||||
GetOpenGLVersion(&major, &minor, &patch);
|
||||
const int need = GLVERNUM(coremajor, coreminor, 0);
|
||||
const int have = GLVERNUM(major, minor, patch);
|
||||
if (have >= need)
|
||||
return true; // we definitely have access to this "extension," as it is part of this version of the GL's core functionality.
|
||||
}
|
||||
|
||||
// okay, see if the GL_EXTENSIONS string reports it.
|
||||
static CDynamicFunctionOpenGL< true, const GLubyte *( APIENTRY *)(GLenum name), const GLubyte * > glGetString("glGetString");
|
||||
if (!glGetString)
|
||||
return false;
|
||||
|
||||
// hacky scanning of this string, because I don't want to spend time breaking it into a vector like I should have.
|
||||
const char *extensions = (const char *) glGetString(GL_EXTENSIONS);
|
||||
const size_t extlen = strlen(ext);
|
||||
while ((extensions) && (*extensions))
|
||||
{
|
||||
const char *ptr = strstr(extensions, ext);
|
||||
#if _WIN32
|
||||
if (!ptr)
|
||||
{
|
||||
static CDynamicFunctionOpenGL< true, const char *( APIENTRY *)( ), const char * > wglGetExtensionsStringEXT("wglGetExtensionsStringEXT");
|
||||
if (wglGetExtensionsStringEXT)
|
||||
{
|
||||
extensions = wglGetExtensionsStringEXT();
|
||||
ptr = strstr(extensions, ext);
|
||||
}
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#elif !defined ( OSX ) && !defined( __ANDROID__ )
|
||||
if (!ptr)
|
||||
{
|
||||
static CDynamicFunctionOpenGL< true, Display *( APIENTRY *)( ), Display* > glXGetCurrentDisplay("glXGetCurrentDisplay");
|
||||
static CDynamicFunctionOpenGL< true, const char *( APIENTRY *)( Display*, int ), const char * > glXQueryExtensionsString("glXQueryExtensionsString");
|
||||
if (glXQueryExtensionsString && glXGetCurrentDisplay)
|
||||
{
|
||||
extensions = glXQueryExtensionsString(glXGetCurrentDisplay(), 0);
|
||||
ptr = strstr(extensions, ext);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ptr)
|
||||
return false;
|
||||
|
||||
// make sure this matches the entire string, and isn't a substring match of some other extension.
|
||||
// if ( ( (string is at start of extension list) or (the char before the string is a space) ) and
|
||||
// (the next char after the string is a space or a null terminator) )
|
||||
if ( ((ptr == extensions) || (ptr[-1] == ' ')) &&
|
||||
((ptr[extlen] == ' ') || (ptr[extlen] == '\0')) )
|
||||
return true; // found it!
|
||||
|
||||
extensions = ptr + extlen; // skip ahead, search again.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CheckOpenGLExtension(const char *ext, const int coremajor, const int coreminor)
|
||||
{
|
||||
const bool retval = CheckOpenGLExtension_internal(ext, coremajor, coreminor);
|
||||
printf("This system %s the OpenGL extension %s.\n", retval ? "supports" : "DOES NOT support", ext);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// The GL context you want entry points for must be current when you hit this constructor!
|
||||
COpenGLEntryPoints::COpenGLEntryPoints()
|
||||
: m_nTotalGLCycles(0)
|
||||
, m_nTotalGLCalls(0)
|
||||
, m_nOpenGLVersionMajor(GetOpenGLVersionMajor())
|
||||
, m_nOpenGLVersionMinor(GetOpenGLVersionMinor())
|
||||
, m_nOpenGLVersionPatch(GetOpenGLVersionPatch())
|
||||
, m_bHave_OpenGL(CheckBaseOpenGLVersion()) // may reset to false as these lookups happen.
|
||||
#define GL_EXT(x,glmajor,glminor) , m_bHave_##x(CheckOpenGLExtension(#x, glmajor, glminor))
|
||||
#define GL_FUNC(ext,req,ret,fn,arg,call) , fn(#fn, m_bHave_##ext)
|
||||
#define GL_FUNC_VOID(ext,req,fn,arg,call) , fn(#fn, m_bHave_##ext)
|
||||
#include "togl/glfuncs.inl"
|
||||
#undef GL_FUNC_VOID
|
||||
#undef GL_FUNC
|
||||
#undef GL_EXT
|
||||
{
|
||||
// Locally cache the copy of the GL device strings, to avoid needing to call these glGet's (which can be extremely slow) more than once.
|
||||
const char *pszString = ( const char * )glGetString(GL_VENDOR);
|
||||
m_pGLDriverStrings[cGLVendorString] = strdup( pszString ? pszString : "" );
|
||||
|
||||
m_nDriverProvider = cGLDriverProviderUnknown;
|
||||
if ( V_stristr( m_pGLDriverStrings[cGLVendorString], "nvidia" ) )
|
||||
m_nDriverProvider = cGLDriverProviderNVIDIA;
|
||||
else if ( V_stristr( m_pGLDriverStrings[cGLVendorString], "amd" ) || V_stristr( m_pGLDriverStrings[cGLVendorString], "ati" ) )
|
||||
m_nDriverProvider = cGLDriverProviderAMD;
|
||||
else if ( V_stristr( m_pGLDriverStrings[cGLVendorString], "intel" ) )
|
||||
m_nDriverProvider = cGLDriverProviderIntelOpenSource;
|
||||
else if ( V_stristr( m_pGLDriverStrings[cGLVendorString], "apple" ) )
|
||||
m_nDriverProvider = cGLDriverProviderApple;
|
||||
|
||||
pszString = ( const char * )glGetString(GL_RENDERER);
|
||||
m_pGLDriverStrings[cGLRendererString] = strdup( pszString ? pszString : "" );
|
||||
|
||||
pszString = ( const char * )glGetString(GL_VERSION);
|
||||
m_pGLDriverStrings[cGLVersionString] = strdup( pszString ? pszString : "" );
|
||||
|
||||
pszString = ( const char * )glGetString(GL_EXTENSIONS);
|
||||
m_pGLDriverStrings[cGLExtensionsString] = strdup( pszString ? pszString : "" );
|
||||
|
||||
printf( "OpenGL: %s %s (%d.%d.%d)\n", m_pGLDriverStrings[ cGLRendererString ], m_pGLDriverStrings[ cGLVersionString ],
|
||||
m_nOpenGLVersionMajor, m_nOpenGLVersionMinor, m_nOpenGLVersionPatch );
|
||||
|
||||
// !!! FIXME: Alfred says the original GL_APPLE_fence code only exists to
|
||||
// !!! FIXME: hint Apple's drivers and not because we rely on the
|
||||
// !!! FIXME: functionality. If so, just remove this check (and the
|
||||
// !!! FIXME: GL_NV_fence code entirely).
|
||||
#ifndef ANDROID // HACK
|
||||
if ((m_bHave_OpenGL) && ((!m_bHave_GL_NV_fence) && (!m_bHave_GL_ARB_sync) && (!m_bHave_GL_APPLE_fence)))
|
||||
{
|
||||
Error( "Required OpenGL extension \"GL_NV_fence\", \"GL_ARB_sync\", or \"GL_APPLE_fence\" is not supported. Please upgrade your OpenGL driver." );
|
||||
}
|
||||
#endif
|
||||
|
||||
// same extension, different name.
|
||||
if (m_bHave_GL_EXT_vertex_array_bgra || m_bHave_GL_ARB_vertex_array_bgra)
|
||||
{
|
||||
m_bHave_GL_EXT_vertex_array_bgra = m_bHave_GL_ARB_vertex_array_bgra = true;
|
||||
}
|
||||
|
||||
// GL_ARB_framebuffer_object is a superset of GL_EXT_framebuffer_object,
|
||||
// (etc) but if you don't call in through the ARB entry points, you won't
|
||||
// get the relaxed restrictions on mismatched attachment dimensions.
|
||||
if (m_bHave_GL_ARB_framebuffer_object)
|
||||
{
|
||||
m_bHave_GL_EXT_framebuffer_object = true;
|
||||
m_bHave_GL_EXT_framebuffer_blit = true;
|
||||
m_bHave_GL_EXT_framebuffer_multisample = true;
|
||||
glBindFramebufferEXT.Force(glBindFramebuffer.Pointer());
|
||||
glBindRenderbufferEXT.Force(glBindRenderbuffer.Pointer());
|
||||
glCheckFramebufferStatusEXT.Force(glCheckFramebufferStatus.Pointer());
|
||||
glDeleteRenderbuffersEXT.Force(glDeleteRenderbuffers.Pointer());
|
||||
glFramebufferRenderbufferEXT.Force(glFramebufferRenderbuffer.Pointer());
|
||||
glFramebufferTexture2DEXT.Force(glFramebufferTexture2D.Pointer());
|
||||
glFramebufferTexture3DEXT.Force(glFramebufferTexture3D.Pointer());
|
||||
glGenFramebuffersEXT.Force(glGenFramebuffers.Pointer());
|
||||
glGenRenderbuffersEXT.Force(glGenRenderbuffers.Pointer());
|
||||
glDeleteFramebuffersEXT.Force(glDeleteFramebuffers.Pointer());
|
||||
glBlitFramebufferEXT.Force(glBlitFramebuffer.Pointer());
|
||||
glRenderbufferStorageMultisampleEXT.Force(glRenderbufferStorageMultisample.Pointer());
|
||||
}
|
||||
|
||||
#if DEBUG_ALL_GLCALLS
|
||||
// push all GL calls through the debug wrappers.
|
||||
#define GL_EXT(x,glmajor,glminor)
|
||||
#define GL_FUNC(ext,req,ret,fn,arg,call) \
|
||||
fn##_gldebugptr = this->fn; \
|
||||
this->fn.Force(fn##_gldebug);
|
||||
#define GL_FUNC_VOID(ext,req,fn,arg,call) \
|
||||
fn##_gldebugptr = this->fn; \
|
||||
this->fn.Force(fn##_gldebug);
|
||||
#include "togl/glfuncs.inl"
|
||||
#undef GL_FUNC_VOID
|
||||
#undef GL_FUNC
|
||||
#undef GL_EXT
|
||||
#endif
|
||||
|
||||
#ifdef OSX
|
||||
m_bHave_GL_NV_bindless_texture = false;
|
||||
m_bHave_GL_AMD_pinned_memory = false;
|
||||
#else
|
||||
if ( ( m_bHave_GL_NV_bindless_texture ) && ( !CommandLine()->CheckParm( "-gl_nv_bindless_texturing" ) ) )
|
||||
{
|
||||
m_bHave_GL_NV_bindless_texture = false;
|
||||
glGetTextureHandleNV.Force( NULL );
|
||||
glGetTextureSamplerHandleNV.Force( NULL );
|
||||
glMakeTextureHandleResidentNV.Force( NULL );
|
||||
glMakeTextureHandleNonResidentNV.Force( NULL );
|
||||
glUniformHandleui64NV.Force( NULL );
|
||||
glUniformHandleui64vNV.Force( NULL );
|
||||
glProgramUniformHandleui64NV.Force( NULL );
|
||||
glProgramUniformHandleui64vNV.Force( NULL );
|
||||
glIsTextureHandleResidentNV.Force( NULL );
|
||||
}
|
||||
|
||||
if ( !CommandLine()->CheckParm( "-gl_amd_pinned_memory" ) )
|
||||
{
|
||||
m_bHave_GL_AMD_pinned_memory = false;
|
||||
}
|
||||
#endif // !OSX
|
||||
|
||||
// Getting reports of black screens, etc. with ARB_buffer_storage and AMD drivers. This type of thing:
|
||||
// http://forums.steampowered.com/forums/showthread.php?t=3266806
|
||||
// So disable it for now.
|
||||
if ( ( m_nDriverProvider == cGLDriverProviderAMD ) || CommandLine()->CheckParm( "-gl_disable_arb_buffer_storage" ) )
|
||||
{
|
||||
m_bHave_GL_ARB_buffer_storage = false;
|
||||
}
|
||||
|
||||
printf( "GL_NV_bindless_texture: %s\n", m_bHave_GL_NV_bindless_texture ? "ENABLED" : "DISABLED" );
|
||||
printf( "GL_AMD_pinned_memory: %s\n", m_bHave_GL_AMD_pinned_memory ? "ENABLED" : "DISABLED" );
|
||||
printf( "GL_ARB_buffer_storage: %s\n", m_bHave_GL_ARB_buffer_storage ? "AVAILABLE" : "NOT AVAILABLE" );
|
||||
printf( "GL_EXT_texture_sRGB_decode: %s\n", m_bHave_GL_EXT_texture_sRGB_decode ? "AVAILABLE" : "NOT AVAILABLE" );
|
||||
|
||||
bool bGLCanDecodeS3TCTextures = m_bHave_GL_EXT_texture_compression_s3tc || ( m_bHave_GL_EXT_texture_compression_dxt1 && m_bHave_GL_ANGLE_texture_compression_dxt3 && m_bHave_GL_ANGLE_texture_compression_dxt5 );
|
||||
if ( !bGLCanDecodeS3TCTextures )
|
||||
{
|
||||
Error( "This application requires either the GL_EXT_texture_compression_s3tc, or the GL_EXT_texture_compression_dxt1 + GL_ANGLE_texture_compression_dxt3 + GL_ANGLE_texture_compression_dxt5 OpenGL extensions. Please install S3TC texture support.\n" );
|
||||
}
|
||||
|
||||
#ifdef OSX
|
||||
if ( CommandLine()->FindParm( "-glmnosrgbdecode" ) )
|
||||
{
|
||||
Msg( "Forcing m_bHave_GL_EXT_texture_sRGB_decode off.\n" );
|
||||
m_bHave_GL_EXT_texture_sRGB_decode = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OSX
|
||||
if ( !m_bHave_GL_EXT_texture_sRGB_decode )
|
||||
{
|
||||
Error( "Required OpenGL extension \"GL_EXT_texture_sRGB_decode\" is not supported. Please update your OpenGL driver.\n" );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
COpenGLEntryPoints::~COpenGLEntryPoints()
|
||||
{
|
||||
for ( uint i = 0; i < cGLTotalDriverProviders; ++i )
|
||||
{
|
||||
free( m_pGLDriverStrings[i] );
|
||||
m_pGLDriverStrings[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void COpenGLEntryPoints::ClearEntryPoints()
|
||||
{
|
||||
#define GL_EXT(x,glmajor,glminor)
|
||||
#define GL_FUNC(ext,req,ret,fn,arg,call) fn.Force( NULL );
|
||||
#define GL_FUNC_VOID(ext,req,fn,arg,call) fn.Force( NULL );
|
||||
#include "togl/glfuncs.inl"
|
||||
#undef GL_FUNC_VOID
|
||||
#undef GL_FUNC
|
||||
#undef GL_EXT
|
||||
}
|
||||
// Turn off memdbg macros (turned on up top) since this is included like a header
|
||||
#include "tier0/memdbgoff.h"
|
||||
|
||||
|
||||
|
6092
togles/linuxwin/glmgr.cpp
Normal file
6092
togles/linuxwin/glmgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
622
togles/linuxwin/glmgr_flush.inl
Normal file
622
togles/linuxwin/glmgr_flush.inl
Normal file
@ -0,0 +1,622 @@
|
||||
// BE VERY VERY CAREFUL what you do in these function. They are extremely hot, and calling the wrong GL API's in here will crush perf. (especially on NVidia threaded drivers).
|
||||
|
||||
FORCEINLINE uint32 bitmix32(uint32 a)
|
||||
{
|
||||
a -= (a<<6);
|
||||
//a ^= (a>>17);
|
||||
//a -= (a<<9);
|
||||
a ^= (a<<4);
|
||||
//a -= (a<<3);
|
||||
//a ^= (a<<10);
|
||||
a ^= (a>>15);
|
||||
return a;
|
||||
}
|
||||
|
||||
#ifndef OSX
|
||||
|
||||
FORCEINLINE GLuint GLMContext::FindSamplerObject( const GLMTexSamplingParams &desiredParams )
|
||||
{
|
||||
int h = bitmix32( desiredParams.m_bits + desiredParams.m_borderColor ) & ( cSamplerObjectHashSize - 1 );
|
||||
while ( ( m_samplerObjectHash[h].m_params.m_bits != desiredParams.m_bits ) || ( m_samplerObjectHash[h].m_params.m_borderColor != desiredParams.m_borderColor ) )
|
||||
{
|
||||
if ( !m_samplerObjectHash[h].m_params.m_packed.m_isValid )
|
||||
break;
|
||||
if ( ++h >= cSamplerObjectHashSize )
|
||||
h = 0;
|
||||
}
|
||||
|
||||
if ( !m_samplerObjectHash[h].m_params.m_packed.m_isValid )
|
||||
{
|
||||
GLMTexSamplingParams &hashParams = m_samplerObjectHash[h].m_params;
|
||||
hashParams = desiredParams;
|
||||
hashParams.SetToSamplerObject( m_samplerObjectHash[h].m_samplerObject );
|
||||
if ( ++m_nSamplerObjectHashNumEntries == cSamplerObjectHashSize )
|
||||
{
|
||||
// TODO: Support resizing
|
||||
Error( "Sampler object hash is full, increase cSamplerObjectHashSize" );
|
||||
}
|
||||
}
|
||||
|
||||
return m_samplerObjectHash[h].m_samplerObject;
|
||||
}
|
||||
|
||||
#endif // !OSX
|
||||
|
||||
// BE VERY CAREFUL WHAT YOU DO IN HERE. This is called on every batch, even seemingly simple changes can kill perf.
|
||||
FORCEINLINE void GLMContext::FlushDrawStates( uint nStartIndex, uint nEndIndex, uint nBaseVertex ) // shadersOn = true for draw calls, false for clear calls
|
||||
{
|
||||
Assert( m_drawingLang == kGLMGLSL ); // no support for ARB shaders right now (and NVidia reports that they aren't worth targeting under Windows/Linux for various reasons anyway)
|
||||
Assert( ( m_drawingFBO == m_boundDrawFBO ) && ( m_drawingFBO == m_boundReadFBO ) ); // this check MUST succeed
|
||||
Assert( m_pDevice->m_pVertDecl );
|
||||
|
||||
#if GLMDEBUG
|
||||
GLM_FUNC;
|
||||
#endif
|
||||
|
||||
GL_BATCH_PERF( m_FlushStats.m_nTotalBatchFlushes++; )
|
||||
|
||||
#if GLMDEBUG
|
||||
bool tex0_srgb = (m_boundDrawFBO[0].m_attach[0].m_tex->m_layout->m_key.m_texFlags & kGLMTexSRGB) != 0;
|
||||
|
||||
// you can only actually use the sRGB FB state on some systems.. check caps
|
||||
if (m_caps.m_hasGammaWrites)
|
||||
{
|
||||
GLBlendEnableSRGB_t writeSRGBState;
|
||||
m_BlendEnableSRGB.Read( &writeSRGBState, 0 ); // the client set value, not the API-written value yet..
|
||||
bool draw_srgb = writeSRGBState.enable != 0;
|
||||
|
||||
if (draw_srgb)
|
||||
{
|
||||
if (tex0_srgb)
|
||||
{
|
||||
// good - draw mode and color tex agree
|
||||
}
|
||||
else
|
||||
{
|
||||
// bad
|
||||
|
||||
// Client has asked to write sRGB into a texture that can't do it.
|
||||
// there is no way to satisfy this unless we change the RT tex and we avoid doing that.
|
||||
// (although we might consider a ** ONE TIME ** promotion.
|
||||
// this shouldn't be a big deal if the tex format is one where it doesn't matter like 32F.
|
||||
|
||||
GLMPRINTF(("-Z- srgb-enabled FBO conflict: attached tex %08x [%s] is not SRGB", m_boundDrawFBO[0].m_attach[0].m_tex, m_boundDrawFBO[0].m_attach[0].m_tex->m_layout->m_layoutSummary ));
|
||||
|
||||
// do we shoot down the srgb-write state for this batch?
|
||||
// I think the runtime will just ignore it.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tex0_srgb)
|
||||
{
|
||||
// odd - client is not writing sRGB into a texture which *can* do it.
|
||||
//GLMPRINTF(( "-Z- srgb-disabled FBO conflict: attached tex %08x [%s] is SRGB", m_boundFBO[0].m_attach[0].m_tex, m_boundFBO[0].m_attach[0].m_tex->m_layout->m_layoutSummary ));
|
||||
//writeSRGBState.enable = true;
|
||||
//m_BlendEnableSRGB.Write( &writeSRGBState );
|
||||
}
|
||||
else
|
||||
{
|
||||
// good - draw mode and color tex agree
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Assert( m_drawingProgram[ kGLMVertexProgram ] );
|
||||
Assert( m_drawingProgram[ kGLMFragmentProgram ] );
|
||||
|
||||
Assert( ( m_drawingProgram[kGLMVertexProgram]->m_type == kGLMVertexProgram ) && ( m_drawingProgram[kGLMFragmentProgram]->m_type == kGLMFragmentProgram ) );
|
||||
Assert( m_drawingProgram[ kGLMVertexProgram ]->m_bTranslatedProgram && m_drawingProgram[ kGLMFragmentProgram ]->m_bTranslatedProgram );
|
||||
|
||||
#if GLMDEBUG
|
||||
// Depth compare mode check
|
||||
uint nCurMask = 1, nShaderSamplerMask = m_drawingProgram[kGLMFragmentProgram]->m_samplerMask;
|
||||
for ( int nSamplerIndex = 0; nSamplerIndex < GLM_SAMPLER_COUNT; ++nSamplerIndex, nCurMask <<= 1 )
|
||||
{
|
||||
if ( !m_samplers[nSamplerIndex].m_pBoundTex )
|
||||
continue;
|
||||
|
||||
if ( m_samplers[nSamplerIndex].m_pBoundTex->m_layout->m_mipCount == 1 )
|
||||
{
|
||||
if ( m_samplers[nSamplerIndex].m_samp.m_packed.m_mipFilter == D3DTEXF_LINEAR )
|
||||
{
|
||||
GLMDebugPrintf( "Sampler %u has mipmap filtering enabled on a texture without mipmaps! (texture name: %s, pixel shader: %s)!\n",
|
||||
nSamplerIndex,
|
||||
m_samplers[nSamplerIndex].m_pBoundTex->m_debugLabel ? m_samplers[nSamplerIndex].m_pBoundTex->m_debugLabel : "?",
|
||||
m_drawingProgram[kGLMFragmentProgram]->m_shaderName );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( nShaderSamplerMask & nCurMask ) == 0 )
|
||||
continue;
|
||||
|
||||
if ( m_samplers[nSamplerIndex].m_pBoundTex->m_layout->m_mipCount == 1 )
|
||||
{
|
||||
if ( m_samplers[nSamplerIndex].m_samp.m_packed.m_mipFilter == D3DTEXF_LINEAR )
|
||||
{
|
||||
// Note this is not always an error - shadow buffer debug visualization shaders purposely want to read shadow depths (and not do the comparison)
|
||||
GLMDebugPrintf( "Sampler %u has mipmap filtering enabled on a texture without mipmaps! (texture name: %s, pixel shader: %s)!\n",
|
||||
nSamplerIndex,
|
||||
m_samplers[nSamplerIndex].m_pBoundTex->m_debugLabel ? m_samplers[nSamplerIndex].m_pBoundTex->m_debugLabel : "?",
|
||||
m_drawingProgram[kGLMFragmentProgram]->m_shaderName );
|
||||
}
|
||||
}
|
||||
|
||||
bool bSamplerIsDepth = ( m_samplers[nSamplerIndex].m_pBoundTex->m_layout->m_key.m_texFlags & kGLMTexIsDepth ) != 0;
|
||||
bool bSamplerShadow = m_samplers[nSamplerIndex].m_samp.m_packed.m_compareMode != 0;
|
||||
|
||||
bool bShaderShadow = ( m_drawingProgram[kGLMFragmentProgram]->m_nShadowDepthSamplerMask & nCurMask ) != 0;
|
||||
|
||||
if ( bShaderShadow )
|
||||
{
|
||||
// Shader expects shadow depth sampling at this sampler index
|
||||
// Must have a depth texture and compare mode must be enabled
|
||||
if ( !bSamplerIsDepth || !bSamplerShadow )
|
||||
{
|
||||
// FIXME: This occasionally occurs in L4D2 when CShaderAPIDx8::ExecuteCommandBuffer() sets the TEXTURE_WHITE texture in the flashlight depth texture slot.
|
||||
GLMDebugPrintf( "Sampler %u's compare mode (%u) or format (depth=%u) is not consistent with pixel shader's compare mode (%u) (texture name: %s, pixel shader: %s)!\n",
|
||||
nSamplerIndex, bSamplerShadow, bSamplerIsDepth, bShaderShadow,
|
||||
m_samplers[nSamplerIndex].m_pBoundTex->m_debugLabel ? m_samplers[nSamplerIndex].m_pBoundTex->m_debugLabel : "?",
|
||||
m_drawingProgram[kGLMFragmentProgram]->m_shaderName );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Shader does not expect shadow depth sampling as this sampler index
|
||||
// We don't care if comparemode is enabled, but we can't have a depth texture in this sampler
|
||||
if ( bSamplerIsDepth )
|
||||
{
|
||||
GLMDebugPrintf( "Sampler %u is a depth texture but the pixel shader's shadow depth sampler mask does not expect depth here (texture name: %s, pixel shader: %s)!\n",
|
||||
nSamplerIndex,
|
||||
m_samplers[nSamplerIndex].m_pBoundTex->m_debugLabel ? m_samplers[nSamplerIndex].m_pBoundTex->m_debugLabel : "?",
|
||||
m_drawingProgram[kGLMFragmentProgram]->m_shaderName );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( m_bDirtyPrograms )
|
||||
{
|
||||
m_bDirtyPrograms = false;
|
||||
|
||||
CGLMShaderPair *pNewPair = m_pairCache->SelectShaderPair( m_drawingProgram[ kGLMVertexProgram ], m_drawingProgram[ kGLMFragmentProgram ], 0 );
|
||||
|
||||
if ( pNewPair != m_pBoundPair )
|
||||
{
|
||||
#if GL_BATCH_TELEMETRY_ZONES
|
||||
tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "NewProgram" );
|
||||
#endif
|
||||
|
||||
if ( !pNewPair->m_valid )
|
||||
{
|
||||
if ( !pNewPair->ValidateProgramPair() )
|
||||
{
|
||||
goto flush_error_exit;
|
||||
}
|
||||
}
|
||||
|
||||
gGL->glUseProgram( (GLuint)pNewPair->m_program );
|
||||
|
||||
GL_BATCH_PERF( m_FlushStats.m_nTotalProgramPairChanges++; )
|
||||
|
||||
if ( !m_pBoundPair )
|
||||
{
|
||||
GL_BATCH_PERF( m_FlushStats.m_nNewPS++; )
|
||||
GL_BATCH_PERF( m_FlushStats.m_nNewVS++; )
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_BATCH_PERF( if ( pNewPair->m_fragmentProg != m_pBoundPair->m_fragmentProg ) m_FlushStats.m_nNewPS++; )
|
||||
GL_BATCH_PERF( if ( pNewPair->m_vertexProg != m_pBoundPair->m_vertexProg ) m_FlushStats.m_nNewVS++; )
|
||||
}
|
||||
|
||||
#if GL_BATCH_PERF_ANALYSIS
|
||||
tmMessage( TELEMETRY_LEVEL2, TMMF_ICON_NOTE, "V:%s (V Regs:%u V Bone Regs:%u) F:%s (F Regs:%u)",
|
||||
m_drawingProgram[ kGLMVertexProgram ]->m_shaderName,
|
||||
m_drawingProgram[ kGLMVertexProgram ]->m_descs[kGLMGLSL].m_highWater,
|
||||
m_drawingProgram[ kGLMVertexProgram ]->m_descs[kGLMGLSL].m_VSHighWaterBone,
|
||||
m_drawingProgram[ kGLMFragmentProgram ]->m_shaderName,
|
||||
m_drawingProgram[ kGLMFragmentProgram ]->m_descs[kGLMGLSL].m_highWater );
|
||||
#endif
|
||||
|
||||
m_pBoundPair = pNewPair;
|
||||
|
||||
// set the dirty levels appropriately since the program changed and has never seen any of the current values.
|
||||
m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = 0;
|
||||
m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = m_drawingProgram[ kGLMVertexProgram ]->m_descs[kGLMGLSL].m_highWater;
|
||||
m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = m_drawingProgram[ kGLMVertexProgram ]->m_descs[kGLMGLSL].m_VSHighWaterBone;
|
||||
|
||||
m_programParamsF[kGLMFragmentProgram].m_firstDirtySlotNonBone = 0;
|
||||
m_programParamsF[kGLMFragmentProgram].m_dirtySlotHighWaterNonBone = m_drawingProgram[ kGLMFragmentProgram ]->m_descs[kGLMGLSL].m_highWater;
|
||||
|
||||
// bool and int dirty levels get set to max, we don't have actual high water marks for them
|
||||
// code which sends the values must clamp on these types.
|
||||
m_programParamsB[kGLMVertexProgram].m_dirtySlotCount = kGLMProgramParamBoolLimit;
|
||||
m_programParamsB[kGLMFragmentProgram].m_dirtySlotCount = kGLMProgramParamBoolLimit;
|
||||
|
||||
m_programParamsI[kGLMVertexProgram].m_dirtySlotCount = kGLMProgramParamInt4Limit;
|
||||
m_programParamsI[kGLMFragmentProgram].m_dirtySlotCount = 0;
|
||||
|
||||
// check fragment buffers used (MRT)
|
||||
if( pNewPair->m_fragmentProg->m_fragDataMask != m_fragDataMask )
|
||||
{
|
||||
gGL->glDrawBuffers( pNewPair->m_fragmentProg->m_numDrawBuffers, pNewPair->m_fragmentProg->m_drawBuffers );
|
||||
m_fragDataMask = pNewPair->m_fragmentProg->m_fragDataMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert( m_ViewportBox.GetData().width == (int)( m_ViewportBox.GetData().widthheight & 0xFFFF ) );
|
||||
Assert( m_ViewportBox.GetData().height == (int)( m_ViewportBox.GetData().widthheight >> 16 ) );
|
||||
|
||||
m_pBoundPair->UpdateScreenUniform( m_ViewportBox.GetData().widthheight );
|
||||
|
||||
GL_BATCH_PERF( m_FlushStats.m_nNumChangedSamplers += m_nNumDirtySamplers );
|
||||
|
||||
#if !defined( OSX ) // no support for sampler objects in OSX 10.6 (GL 2.1 profile)
|
||||
if ( m_bUseSamplerObjects)
|
||||
{
|
||||
while ( m_nNumDirtySamplers )
|
||||
{
|
||||
const uint nSamplerIndex = m_nDirtySamplers[--m_nNumDirtySamplers];
|
||||
Assert( ( nSamplerIndex < GLM_SAMPLER_COUNT ) && ( !m_nDirtySamplerFlags[nSamplerIndex]) );
|
||||
|
||||
m_nDirtySamplerFlags[nSamplerIndex] = 1;
|
||||
|
||||
gGL->glBindSampler( nSamplerIndex, FindSamplerObject( m_samplers[nSamplerIndex].m_samp ) );
|
||||
|
||||
GL_BATCH_PERF( m_FlushStats.m_nNumSamplingParamsChanged++ );
|
||||
|
||||
#if defined( OSX ) // valid for OSX only if using GL 3.3 context
|
||||
CGLMTex *pTex = m_samplers[nSamplerIndex].m_pBoundTex;
|
||||
|
||||
if( pTex && !( gGL->m_bHave_GL_EXT_texture_sRGB_decode ) )
|
||||
{
|
||||
// see if requested SRGB state differs from the known one
|
||||
bool texSRGB = ( pTex->m_layout->m_key.m_texFlags & kGLMTexSRGB ) != 0;
|
||||
bool glSampSRGB = m_samplers[nSamplerIndex].m_samp.m_packed.m_srgb;
|
||||
|
||||
if ( texSRGB != glSampSRGB ) // mismatch
|
||||
{
|
||||
pTex->HandleSRGBMismatch( glSampSRGB, pTex->m_srgbFlipCount );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // if !defined( OSX )
|
||||
{
|
||||
while ( m_nNumDirtySamplers )
|
||||
{
|
||||
const uint nSamplerIndex = m_nDirtySamplers[--m_nNumDirtySamplers];
|
||||
Assert( ( nSamplerIndex < GLM_SAMPLER_COUNT ) && ( !m_nDirtySamplerFlags[nSamplerIndex]) );
|
||||
|
||||
m_nDirtySamplerFlags[nSamplerIndex] = 1;
|
||||
|
||||
CGLMTex *pTex = m_samplers[nSamplerIndex].m_pBoundTex;
|
||||
|
||||
if ( ( pTex ) && ( !( pTex->m_SamplingParams == m_samplers[nSamplerIndex].m_samp ) ) )
|
||||
{
|
||||
SelectTMU( nSamplerIndex );
|
||||
|
||||
m_samplers[nSamplerIndex].m_samp.DeltaSetToTarget( pTex->m_texGLTarget, pTex->m_SamplingParams );
|
||||
|
||||
pTex->m_SamplingParams = m_samplers[nSamplerIndex].m_samp;
|
||||
|
||||
#if defined( OSX )
|
||||
if( pTex && !( gGL->m_bHave_GL_EXT_texture_sRGB_decode ) )
|
||||
{
|
||||
// see if requested SRGB state differs from the known one
|
||||
bool texSRGB = ( pTex->m_layout->m_key.m_texFlags & kGLMTexSRGB ) != 0;
|
||||
bool glSampSRGB = m_samplers[nSamplerIndex].m_samp.m_packed.m_srgb;
|
||||
|
||||
if ( texSRGB != glSampSRGB ) // mismatch
|
||||
{
|
||||
pTex->HandleSRGBMismatch( glSampSRGB, pTex->m_srgbFlipCount );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vertex stage --------------------------------------------------------------------
|
||||
if ( m_bUseBoneUniformBuffers )
|
||||
{
|
||||
// vertex stage --------------------------------------------------------------------
|
||||
if ( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone )
|
||||
{
|
||||
int firstDirtySlot = m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone;
|
||||
int dirtySlotHighWater = MIN( m_drawingProgram[kGLMVertexProgram]->m_descs[kGLMGLSL].m_highWater, m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone );
|
||||
|
||||
GLint vconstLoc = m_pBoundPair->m_locVertexParams;
|
||||
if ( ( vconstLoc >= 0 ) && ( dirtySlotHighWater > firstDirtySlot ) )
|
||||
{
|
||||
#if GL_BATCH_TELEMETRY_ZONES
|
||||
tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "VSNonBoneUniformUpdate %u %u", firstDirtySlot, dirtySlotHighWater );
|
||||
#endif
|
||||
int numSlots = dirtySlotHighWater - DXABSTRACT_VS_FIRST_BONE_SLOT;
|
||||
|
||||
// consts after the bones (c217 onwards), since we use the concatenated destination array vc[], upload these consts starting from vc[58]
|
||||
if( numSlots > 0 )
|
||||
{
|
||||
gGL->glUniform4fv( m_pBoundPair->m_UniformBufferParams[kGLMVertexProgram][DXABSTRACT_VS_FIRST_BONE_SLOT], numSlots, &m_programParamsF[kGLMVertexProgram].m_values[(DXABSTRACT_VS_LAST_BONE_SLOT+1)][0] );
|
||||
|
||||
dirtySlotHighWater = DXABSTRACT_VS_FIRST_BONE_SLOT;
|
||||
|
||||
GL_BATCH_PERF( m_nTotalVSUniformCalls++; )
|
||||
GL_BATCH_PERF( m_nTotalVSUniformsSet += numSlots; )
|
||||
|
||||
GL_BATCH_PERF( m_FlushStats.m_nFirstVSConstant = DXABSTRACT_VS_FIRST_BONE_SLOT; )
|
||||
GL_BATCH_PERF( m_FlushStats.m_nNumVSConstants += numSlots; )
|
||||
}
|
||||
|
||||
numSlots = dirtySlotHighWater - firstDirtySlot;
|
||||
|
||||
// consts before the bones (c0-c57)
|
||||
if( numSlots > 0 )
|
||||
{
|
||||
gGL->glUniform4fv( m_pBoundPair->m_UniformBufferParams[kGLMVertexProgram][firstDirtySlot], dirtySlotHighWater - firstDirtySlot, &m_programParamsF[kGLMVertexProgram].m_values[firstDirtySlot][0] );
|
||||
|
||||
GL_BATCH_PERF( m_nTotalVSUniformCalls++; )
|
||||
GL_BATCH_PERF( m_nTotalVSUniformsSet += dirtySlotHighWater - firstDirtySlot; )
|
||||
|
||||
GL_BATCH_PERF( m_FlushStats.m_nFirstVSConstant = firstDirtySlot; )
|
||||
GL_BATCH_PERF( m_FlushStats.m_nNumVSConstants += (dirtySlotHighWater - firstDirtySlot); )
|
||||
}
|
||||
}
|
||||
|
||||
m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = 256;
|
||||
m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = 0;
|
||||
}
|
||||
|
||||
if ( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone )
|
||||
{
|
||||
const GLint vconstBoneLoc = m_pBoundPair->m_locVertexBoneParams;
|
||||
if ( vconstBoneLoc >= 0 )
|
||||
{
|
||||
int shaderSlotsBone = 0;
|
||||
if ( ( m_drawingProgram[kGLMVertexProgram]->m_descs[kGLMGLSL].m_VSHighWaterBone > 0 ) && ( m_nMaxUsedVertexProgramConstantsHint > DXABSTRACT_VS_FIRST_BONE_SLOT ) )
|
||||
{
|
||||
shaderSlotsBone = MIN( m_drawingProgram[kGLMVertexProgram]->m_descs[kGLMGLSL].m_VSHighWaterBone, m_nMaxUsedVertexProgramConstantsHint - DXABSTRACT_VS_FIRST_BONE_SLOT );
|
||||
}
|
||||
|
||||
int dirtySlotHighWaterBone = MIN( shaderSlotsBone, m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone );
|
||||
if ( dirtySlotHighWaterBone )
|
||||
{
|
||||
uint nNumBoneRegs = dirtySlotHighWaterBone;
|
||||
|
||||
#if GL_BATCH_TELEMETRY_ZONES
|
||||
tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "VSBoneUniformUpdate %u", nNumBoneRegs );
|
||||
#endif
|
||||
|
||||
gGL->glUniform4fv( vconstBoneLoc, nNumBoneRegs, &m_programParamsF[kGLMVertexProgram].m_values[DXABSTRACT_VS_FIRST_BONE_SLOT][0] );
|
||||
|
||||
GL_BATCH_PERF( m_nTotalVSUniformBoneCalls++; )
|
||||
GL_BATCH_PERF( m_nTotalVSUniformsBoneSet += nNumBoneRegs; )
|
||||
GL_BATCH_PERF( m_FlushStats.m_nNumVSBoneConstants += nNumBoneRegs; )
|
||||
}
|
||||
|
||||
m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone )
|
||||
{
|
||||
const int nMaxUsedShaderSlots = m_drawingProgram[kGLMVertexProgram]->m_descs[kGLMGLSL].m_highWater;
|
||||
|
||||
int firstDirtySlot = m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone;
|
||||
int dirtySlotHighWater = MIN( nMaxUsedShaderSlots, m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone );
|
||||
|
||||
GLint vconstLoc = m_pBoundPair->m_locVertexParams;
|
||||
if ( ( vconstLoc >= 0 ) && ( dirtySlotHighWater > firstDirtySlot ) )
|
||||
{
|
||||
#if GL_BATCH_TELEMETRY_ZONES
|
||||
tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "VSNonBoneUniformUpdate %u %u", firstDirtySlot, dirtySlotHighWater );
|
||||
#endif
|
||||
gGL->glUniform4fv( m_pBoundPair->m_UniformBufferParams[kGLMVertexProgram][firstDirtySlot], dirtySlotHighWater - firstDirtySlot, &m_programParamsF[kGLMVertexProgram].m_values[firstDirtySlot][0] );
|
||||
|
||||
GL_BATCH_PERF( m_nTotalVSUniformCalls++; )
|
||||
GL_BATCH_PERF( m_nTotalVSUniformsSet += dirtySlotHighWater - firstDirtySlot; )
|
||||
|
||||
GL_BATCH_PERF( m_FlushStats.m_nFirstVSConstant = firstDirtySlot; )
|
||||
GL_BATCH_PERF( m_FlushStats.m_nNumVSConstants += (dirtySlotHighWater - firstDirtySlot); )
|
||||
}
|
||||
|
||||
m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = 256;
|
||||
m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// see if VS uses i0, b0, b1, b2, b3.
|
||||
// use a glUniform1i to set any one of these if active. skip all of them if no dirties reported.
|
||||
// my kingdom for the UBO extension!
|
||||
|
||||
// ------- bools ---------- //
|
||||
if ( m_pBoundPair->m_bHasBoolOrIntUniforms )
|
||||
{
|
||||
if ( m_programParamsB[kGLMVertexProgram].m_dirtySlotCount ) // optimize this later after the float param pushes are proven out
|
||||
{
|
||||
const uint nLimit = MIN( CGLMShaderPair::cMaxVertexShaderBoolUniforms, m_programParamsB[kGLMVertexProgram].m_dirtySlotCount );
|
||||
for ( uint i = 0; i < nLimit; ++i )
|
||||
{
|
||||
GLint constBoolLoc = m_pBoundPair->m_locVertexBool[i];
|
||||
if ( constBoolLoc >= 0 )
|
||||
gGL->glUniform1i( constBoolLoc, m_programParamsB[kGLMVertexProgram].m_values[i] );
|
||||
}
|
||||
|
||||
m_programParamsB[kGLMVertexProgram].m_dirtySlotCount = 0;
|
||||
}
|
||||
|
||||
if ( m_programParamsB[kGLMFragmentProgram].m_dirtySlotCount ) // optimize this later after the float param pushes are proven out
|
||||
{
|
||||
const uint nLimit = MIN( CGLMShaderPair::cMaxFragmentShaderBoolUniforms, m_programParamsB[kGLMFragmentProgram].m_dirtySlotCount );
|
||||
for ( uint i = 0; i < nLimit; ++i )
|
||||
{
|
||||
GLint constBoolLoc = m_pBoundPair->m_locFragmentBool[i];
|
||||
if ( constBoolLoc >= 0 )
|
||||
gGL->glUniform1i( constBoolLoc, m_programParamsB[kGLMFragmentProgram].m_values[i] );
|
||||
}
|
||||
|
||||
m_programParamsB[kGLMFragmentProgram].m_dirtySlotCount = 0;
|
||||
}
|
||||
|
||||
if ( m_programParamsI[kGLMVertexProgram].m_dirtySlotCount )
|
||||
{
|
||||
GLint vconstInt0Loc = m_pBoundPair->m_locVertexInteger0; //glGetUniformLocationARB( prog, "i0");
|
||||
if ( vconstInt0Loc >= 0 )
|
||||
{
|
||||
gGL->glUniform1i( vconstInt0Loc, m_programParamsI[kGLMVertexProgram].m_values[0][0] ); //FIXME magic number
|
||||
}
|
||||
m_programParamsI[kGLMVertexProgram].m_dirtySlotCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Assert( ( m_pDevice->m_streams[0].m_vtxBuffer && ( m_pDevice->m_streams[0].m_vtxBuffer->m_vtxBuffer == m_pDevice->m_vtx_buffers[0] ) ) || ( ( !m_pDevice->m_streams[0].m_vtxBuffer ) && ( m_pDevice->m_vtx_buffers[0] == m_pDevice->m_pDummy_vtx_buffer ) ) );
|
||||
Assert( ( m_pDevice->m_streams[1].m_vtxBuffer && ( m_pDevice->m_streams[1].m_vtxBuffer->m_vtxBuffer == m_pDevice->m_vtx_buffers[1] ) ) || ( ( !m_pDevice->m_streams[1].m_vtxBuffer ) && ( m_pDevice->m_vtx_buffers[1] == m_pDevice->m_pDummy_vtx_buffer ) ) );
|
||||
Assert( ( m_pDevice->m_streams[2].m_vtxBuffer && ( m_pDevice->m_streams[2].m_vtxBuffer->m_vtxBuffer == m_pDevice->m_vtx_buffers[2] ) ) || ( ( !m_pDevice->m_streams[2].m_vtxBuffer ) && ( m_pDevice->m_vtx_buffers[2] == m_pDevice->m_pDummy_vtx_buffer ) ) );
|
||||
Assert( ( m_pDevice->m_streams[3].m_vtxBuffer && ( m_pDevice->m_streams[3].m_vtxBuffer->m_vtxBuffer == m_pDevice->m_vtx_buffers[3] ) ) || ( ( !m_pDevice->m_streams[3].m_vtxBuffer ) && ( m_pDevice->m_vtx_buffers[3] == m_pDevice->m_pDummy_vtx_buffer ) ) );
|
||||
|
||||
uint nCurTotalBufferRevision;
|
||||
nCurTotalBufferRevision = m_pDevice->m_vtx_buffers[0]->m_nRevision + m_pDevice->m_vtx_buffers[1]->m_nRevision + m_pDevice->m_vtx_buffers[2]->m_nRevision + m_pDevice->m_vtx_buffers[3]->m_nRevision;
|
||||
|
||||
// If any of these inputs have changed, we need to enumerate through all of the expected GL vertex attribs and modify anything in the GL layer that have changed.
|
||||
// This is not always a win, but it is a net win on NVidia (by 1-4.8% depending on whether driver threading is enabled).
|
||||
if ( ( nCurTotalBufferRevision != m_CurAttribs.m_nTotalBufferRevision ) ||
|
||||
( m_CurAttribs.m_pVertDecl != m_pDevice->m_pVertDecl ) ||
|
||||
( m_CurAttribs.m_vtxAttribMap[0] != reinterpret_cast<const uint64 *>(m_pDevice->m_vertexShader->m_vtxAttribMap)[0] ) ||
|
||||
( m_CurAttribs.m_vtxAttribMap[1] != reinterpret_cast<const uint64 *>(m_pDevice->m_vertexShader->m_vtxAttribMap)[1] ) ||
|
||||
( memcmp( m_CurAttribs.m_streams, m_pDevice->m_streams, sizeof( m_pDevice->m_streams ) ) != 0 ) )
|
||||
{
|
||||
// This branch is taken 52.2% of the time in the L4D2 test1 (long) timedemo.
|
||||
|
||||
#if GL_BATCH_TELEMETRY_ZONES
|
||||
tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "SetVertexAttribs" );
|
||||
#endif
|
||||
|
||||
m_CurAttribs.m_nTotalBufferRevision = nCurTotalBufferRevision;
|
||||
m_CurAttribs.m_pVertDecl = m_pDevice->m_pVertDecl;
|
||||
m_CurAttribs.m_vtxAttribMap[0] = reinterpret_cast<const uint64 *>(m_pDevice->m_vertexShader->m_vtxAttribMap)[0];
|
||||
m_CurAttribs.m_vtxAttribMap[1] = reinterpret_cast<const uint64 *>(m_pDevice->m_vertexShader->m_vtxAttribMap)[1];
|
||||
memcpy( m_CurAttribs.m_streams, m_pDevice->m_streams, sizeof( m_pDevice->m_streams ) );
|
||||
|
||||
unsigned char *pVertexShaderAttribMap = m_pDevice->m_vertexShader->m_vtxAttribMap;
|
||||
const int nMaxVertexAttributesToCheck = m_drawingProgram[ kGLMVertexProgram ]->m_maxVertexAttrs;
|
||||
|
||||
IDirect3DVertexDeclaration9 *pVertDecl = m_pDevice->m_pVertDecl;
|
||||
const uint8 *pVertexAttribDescToStreamIndex = pVertDecl->m_VertexAttribDescToStreamIndex;
|
||||
|
||||
for( int nMask = 1, nIndex = 0; nIndex < nMaxVertexAttributesToCheck; ++nIndex, nMask <<= 1 )
|
||||
{
|
||||
uint8 vertexShaderAttrib = pVertexShaderAttribMap[ nIndex ];
|
||||
|
||||
uint nDeclIndex = pVertexAttribDescToStreamIndex[vertexShaderAttrib];
|
||||
if ( nDeclIndex == 0xFF )
|
||||
{
|
||||
// Not good - the vertex shader has an attribute which can't be located in the decl!
|
||||
// The D3D9 debug runtime is also going to complain.
|
||||
Assert( 0 );
|
||||
|
||||
if ( m_lastKnownVertexAttribMask & nMask )
|
||||
{
|
||||
m_lastKnownVertexAttribMask &= ~nMask;
|
||||
gGL->glDisableVertexAttribArray( nIndex );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
D3DVERTEXELEMENT9_GL *pDeclElem = &pVertDecl->m_elements[nDeclIndex];
|
||||
|
||||
Assert( ( ( vertexShaderAttrib >> 4 ) == pDeclElem->m_dxdecl.Usage ) && ( ( vertexShaderAttrib & 0x0F ) == pDeclElem->m_dxdecl.UsageIndex) );
|
||||
|
||||
const uint nStreamIndex = pDeclElem->m_dxdecl.Stream;
|
||||
const D3DStreamDesc *pStream = &m_pDevice->m_streams[ nStreamIndex ];
|
||||
|
||||
CGLMBuffer *pBuf = m_pDevice->m_vtx_buffers[ nStreamIndex ];
|
||||
if ( pBuf == m_pDevice->m_pDummy_vtx_buffer )
|
||||
{
|
||||
Assert( pStream->m_vtxBuffer == NULL );
|
||||
|
||||
// this shader doesn't use that pair.
|
||||
if ( m_lastKnownVertexAttribMask & nMask )
|
||||
{
|
||||
m_lastKnownVertexAttribMask &= ~nMask;
|
||||
gGL->glDisableVertexAttribArray( nIndex );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Assert( pStream->m_vtxBuffer->m_vtxBuffer == pBuf );
|
||||
|
||||
int nBufOffset = pDeclElem->m_gldecl.m_offset + pStream->m_offset;
|
||||
Assert( nBufOffset >= 0 );
|
||||
Assert( nBufOffset < (int)pBuf->m_nSize );
|
||||
if ( pBuf->m_bUsingPersistentBuffer )
|
||||
{
|
||||
nBufOffset += pBuf->m_nPersistentBufferStartOffset;
|
||||
}
|
||||
|
||||
SetBufAndVertexAttribPointer( nIndex, pBuf->GetHandle(),
|
||||
pStream->m_stride, pDeclElem->m_gldecl.m_datatype, pDeclElem->m_gldecl.m_normalized, pDeclElem->m_gldecl.m_nCompCount,
|
||||
reinterpret_cast< const GLvoid * >( reinterpret_cast< int >( pBuf->m_pPseudoBuf ) + nBufOffset ),
|
||||
pBuf->m_nRevision );
|
||||
|
||||
if ( !( m_lastKnownVertexAttribMask & nMask ) )
|
||||
{
|
||||
m_lastKnownVertexAttribMask |= nMask;
|
||||
gGL->glEnableVertexAttribArray( nIndex );
|
||||
}
|
||||
}
|
||||
|
||||
for( int nIndex = nMaxVertexAttributesToCheck; nIndex < m_nNumSetVertexAttributes; nIndex++ )
|
||||
{
|
||||
gGL->glDisableVertexAttribArray( nIndex );
|
||||
m_lastKnownVertexAttribMask &= ~(1 << nIndex);
|
||||
}
|
||||
|
||||
m_nNumSetVertexAttributes = nMaxVertexAttributesToCheck;
|
||||
}
|
||||
|
||||
// fragment stage --------------------------------------------------------------------
|
||||
if ( m_programParamsF[kGLMFragmentProgram].m_dirtySlotHighWaterNonBone )
|
||||
{
|
||||
GLint fconstLoc;
|
||||
fconstLoc = m_pBoundPair->m_locFragmentParams;
|
||||
if ( fconstLoc >= 0 )
|
||||
{
|
||||
const int nMaxUsedShaderSlots = m_drawingProgram[kGLMFragmentProgram]->m_descs[kGLMGLSL].m_highWater;
|
||||
|
||||
int firstDirtySlot = m_programParamsF[kGLMFragmentProgram].m_firstDirtySlotNonBone;
|
||||
int dirtySlotHighWater = MIN( nMaxUsedShaderSlots, m_programParamsF[kGLMFragmentProgram].m_dirtySlotHighWaterNonBone );
|
||||
|
||||
if ( dirtySlotHighWater > firstDirtySlot )
|
||||
{
|
||||
#if GL_BATCH_TELEMETRY_ZONES
|
||||
tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "PSUniformUpdate %u %u", firstDirtySlot, dirtySlotHighWater );
|
||||
#endif
|
||||
|
||||
gGL->glUniform4fv( m_pBoundPair->m_UniformBufferParams[kGLMFragmentProgram][firstDirtySlot], dirtySlotHighWater - firstDirtySlot, &m_programParamsF[kGLMFragmentProgram].m_values[firstDirtySlot][0] );
|
||||
|
||||
GL_BATCH_PERF( m_nTotalPSUniformCalls++; )
|
||||
GL_BATCH_PERF( m_nTotalPSUniformsSet += dirtySlotHighWater - firstDirtySlot; )
|
||||
|
||||
GL_BATCH_PERF( m_FlushStats.m_nFirstPSConstant = firstDirtySlot; )
|
||||
GL_BATCH_PERF( m_FlushStats.m_nNumPSConstants += (dirtySlotHighWater - firstDirtySlot); )
|
||||
}
|
||||
m_programParamsF[kGLMFragmentProgram].m_firstDirtySlotNonBone = 256;
|
||||
m_programParamsF[kGLMFragmentProgram].m_dirtySlotHighWaterNonBone = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
flush_error_exit:
|
||||
m_pBoundPair = NULL;
|
||||
m_bDirtyPrograms = true;
|
||||
return;
|
||||
}
|
4688
togles/linuxwin/glmgrbasics.cpp
Normal file
4688
togles/linuxwin/glmgrbasics.cpp
Normal file
File diff suppressed because it is too large
Load Diff
34
togles/linuxwin/glmgrcocoa.mm
Normal file
34
togles/linuxwin/glmgrcocoa.mm
Normal file
@ -0,0 +1,34 @@
|
||||
//========= Copyright 1996-2009, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: provide some call-out glue to ObjC from the C++ GLMgr code
|
||||
//
|
||||
// $Revision: $
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
|
||||
#undef MIN
|
||||
#undef MAX
|
||||
#define DONT_DEFINE_BOOL // Don't define BOOL!
|
||||
#include "tier0/threadtools.h"
|
||||
#include "tier1/interface.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier1/utllinkedlist.h"
|
||||
#include "togl/rendermechanism.h"
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------ //
|
||||
// some glue to let GLMgr call into NS/ObjC classes.
|
||||
// ------------------------------------------------------------------------------------ //
|
||||
|
||||
CGLContextObj GetCGLContextFromNSGL( PseudoNSGLContextPtr nsglCtx )
|
||||
{
|
||||
return (CGLContextObj)[ (NSOpenGLContext*)nsglCtx CGLContextObj];
|
||||
}
|
||||
|
29
togles/linuxwin/glmtexinlines.h
Normal file
29
togles/linuxwin/glmtexinlines.h
Normal file
@ -0,0 +1,29 @@
|
||||
//========= 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.
|
||||
#ifndef CGLMTEXINLINES_H
|
||||
#define CGLMTEXINLINES_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#endif // CGLMTEXINLINES_H
|
71
togles/linuxwin/intelglmallocworkaround.cpp
Normal file
71
togles/linuxwin/intelglmallocworkaround.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
//========= 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.
|
||||
#include "intelglmallocworkaround.h"
|
||||
#include "mach_override.h"
|
||||
|
||||
// memdbgon -must- be the last include file in a .cpp file.
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
IntelGLMallocWorkaround* IntelGLMallocWorkaround::s_pWorkaround = NULL;
|
||||
|
||||
void *IntelGLMallocWorkaround::ZeroingAlloc(size_t size)
|
||||
{
|
||||
// We call into this pointer that resumes the original malloc.
|
||||
void *memory = s_pWorkaround->m_pfnMallocReentry(size);
|
||||
if (size < 96)
|
||||
{
|
||||
// Since the Intel driver has an issue with a small allocation
|
||||
// that's left uninitialized, we use memset to ensure it's zero-initialized.
|
||||
memset(memory, 0, size);
|
||||
}
|
||||
|
||||
return memory;
|
||||
}
|
||||
|
||||
IntelGLMallocWorkaround* IntelGLMallocWorkaround::Get()
|
||||
{
|
||||
if (!s_pWorkaround)
|
||||
{
|
||||
s_pWorkaround = new IntelGLMallocWorkaround();
|
||||
}
|
||||
|
||||
return s_pWorkaround;
|
||||
}
|
||||
|
||||
bool IntelGLMallocWorkaround::Enable()
|
||||
{
|
||||
if ( m_pfnMallocReentry != NULL )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
mach_error_t error = mach_override_ptr( (void*)&malloc, (const void*)&ZeroingAlloc, (void**)&m_pfnMallocReentry );
|
||||
if ( error == err_cannot_override )
|
||||
{
|
||||
m_pfnMallocReentry = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
61
togles/linuxwin/intelglmallocworkaround.h
Normal file
61
togles/linuxwin/intelglmallocworkaround.h
Normal file
@ -0,0 +1,61 @@
|
||||
//========= 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.
|
||||
//
|
||||
// intelglmallocworkaround.h
|
||||
// class responsible for setting up a malloc override that zeroes allocated
|
||||
// memory of less than 96 bytes. this is to work around a bug
|
||||
// in the Intel GLSL compiler on Mac OS X 10.8 due to uninitialized memory.
|
||||
//
|
||||
// 96 was chosen due to this quote from Apple:
|
||||
// "I verified that the size of the structure is exactly 64 bytes on 10.8.3, 10.8.4 and will be on 10.8.5."
|
||||
//
|
||||
// certain GLSL shaders would (intermittently) cause a crash the first time they
|
||||
// were drawn, and the bug has supposedly been fixed in 10.9, but is unlikely to
|
||||
// ever make it to 10.8.
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef INTELGLMALLOCWORKAROUND_H
|
||||
#define INTELGLMALLOCWORKAROUND_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
class IntelGLMallocWorkaround
|
||||
{
|
||||
public:
|
||||
static IntelGLMallocWorkaround *Get();
|
||||
bool Enable();
|
||||
|
||||
protected:
|
||||
IntelGLMallocWorkaround() :m_pfnMallocReentry(NULL) {}
|
||||
~IntelGLMallocWorkaround() {}
|
||||
|
||||
static IntelGLMallocWorkaround *s_pWorkaround;
|
||||
static void* ZeroingAlloc(size_t);
|
||||
|
||||
typedef void* (*pfnMalloc_t)(size_t);
|
||||
pfnMalloc_t m_pfnMallocReentry;
|
||||
};
|
||||
|
||||
#endif // INTELGLMALLOCWORKAROUND_H
|
765
togles/linuxwin/mach_override.c
Normal file
765
togles/linuxwin/mach_override.c
Normal file
@ -0,0 +1,765 @@
|
||||
// mach_override.c semver:1.2.0
|
||||
// Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com
|
||||
// Some rights reserved: http://opensource.org/licenses/mit
|
||||
// https://github.com/rentzsch/mach_override
|
||||
|
||||
#include "mach_override.h"
|
||||
|
||||
#include <mach-o/dyld.h>
|
||||
#include <mach/mach_host.h>
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/vm_map.h>
|
||||
#include <sys/mman.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
/**************************
|
||||
*
|
||||
* Constants
|
||||
*
|
||||
**************************/
|
||||
#pragma mark -
|
||||
#pragma mark (Constants)
|
||||
|
||||
#define kPageSize 4096
|
||||
#if defined(__ppc__) || defined(__POWERPC__)
|
||||
|
||||
long kIslandTemplate[] = {
|
||||
0x9001FFFC, // stw r0,-4(SP)
|
||||
0x3C00DEAD, // lis r0,0xDEAD
|
||||
0x6000BEEF, // ori r0,r0,0xBEEF
|
||||
0x7C0903A6, // mtctr r0
|
||||
0x8001FFFC, // lwz r0,-4(SP)
|
||||
0x60000000, // nop ; optionally replaced
|
||||
0x4E800420 // bctr
|
||||
};
|
||||
|
||||
#define kAddressHi 3
|
||||
#define kAddressLo 5
|
||||
#define kInstructionHi 10
|
||||
#define kInstructionLo 11
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
#define kOriginalInstructionsSize 16
|
||||
// On X86 we migh need to instert an add with a 32 bit immediate after the
|
||||
// original instructions.
|
||||
#define kMaxFixupSizeIncrease 5
|
||||
|
||||
unsigned char kIslandTemplate[] = {
|
||||
// kOriginalInstructionsSize nop instructions so that we
|
||||
// should have enough space to host original instructions
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
// Now the real jump instruction
|
||||
0xE9, 0xEF, 0xBE, 0xAD, 0xDE
|
||||
};
|
||||
|
||||
#define kInstructions 0
|
||||
#define kJumpAddress kInstructions + kOriginalInstructionsSize + 1
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
#define kOriginalInstructionsSize 32
|
||||
// On X86-64 we never need to instert a new instruction.
|
||||
#define kMaxFixupSizeIncrease 0
|
||||
|
||||
#define kJumpAddress kOriginalInstructionsSize + 6
|
||||
|
||||
unsigned char kIslandTemplate[] = {
|
||||
// kOriginalInstructionsSize nop instructions so that we
|
||||
// should have enough space to host original instructions
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
// Now the real jump instruction
|
||||
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**************************
|
||||
*
|
||||
* Data Types
|
||||
*
|
||||
**************************/
|
||||
#pragma mark -
|
||||
#pragma mark (Data Types)
|
||||
|
||||
typedef struct {
|
||||
char instructions[sizeof(kIslandTemplate)];
|
||||
} BranchIsland;
|
||||
|
||||
/**************************
|
||||
*
|
||||
* Funky Protos
|
||||
*
|
||||
**************************/
|
||||
#pragma mark -
|
||||
#pragma mark (Funky Protos)
|
||||
|
||||
static mach_error_t
|
||||
allocateBranchIsland(
|
||||
BranchIsland **island,
|
||||
void *originalFunctionAddress);
|
||||
|
||||
mach_error_t
|
||||
freeBranchIsland(
|
||||
BranchIsland *island );
|
||||
|
||||
#if defined(__ppc__) || defined(__POWERPC__)
|
||||
mach_error_t
|
||||
setBranchIslandTarget(
|
||||
BranchIsland *island,
|
||||
const void *branchTo,
|
||||
long instruction );
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
mach_error_t
|
||||
setBranchIslandTarget_i386(
|
||||
BranchIsland *island,
|
||||
const void *branchTo,
|
||||
char* instructions );
|
||||
void
|
||||
atomic_mov64(
|
||||
uint64_t *targetAddress,
|
||||
uint64_t value );
|
||||
|
||||
static Boolean
|
||||
eatKnownInstructions(
|
||||
unsigned char *code,
|
||||
uint64_t *newInstruction,
|
||||
int *howManyEaten,
|
||||
char *originalInstructions,
|
||||
int *originalInstructionCount,
|
||||
uint8_t *originalInstructionSizes );
|
||||
|
||||
static void
|
||||
fixupInstructions(
|
||||
uint32_t offset,
|
||||
void *instructionsToFix,
|
||||
int instructionCount,
|
||||
uint8_t *instructionSizes );
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Interface
|
||||
*
|
||||
*******************************************************************************/
|
||||
#pragma mark -
|
||||
#pragma mark (Interface)
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
mach_error_t makeIslandExecutable(void *address) {
|
||||
mach_error_t err = err_none;
|
||||
uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1);
|
||||
int e = err_none;
|
||||
e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
|
||||
e |= msync((void *)page, kPageSize, MS_INVALIDATE );
|
||||
if (e) {
|
||||
err = err_cannot_override;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
mach_error_t
|
||||
mach_override_ptr(
|
||||
void *originalFunctionAddress,
|
||||
const void *overrideFunctionAddress,
|
||||
void **originalFunctionReentryIsland )
|
||||
{
|
||||
assert( originalFunctionAddress );
|
||||
assert( overrideFunctionAddress );
|
||||
|
||||
// this addresses overriding such functions as AudioOutputUnitStart()
|
||||
// test with modified DefaultOutputUnit project
|
||||
#if defined(__x86_64__)
|
||||
for(;;){
|
||||
if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp qword near [rip+0x????????]
|
||||
originalFunctionAddress=*(void**)((char*)originalFunctionAddress+6+*(int32_t *)((uint16_t*)originalFunctionAddress+1));
|
||||
else break;
|
||||
}
|
||||
#elif defined(__i386__)
|
||||
for(;;){
|
||||
if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp *0x????????
|
||||
originalFunctionAddress=**(void***)((uint16_t*)originalFunctionAddress+1);
|
||||
else break;
|
||||
}
|
||||
#endif
|
||||
|
||||
long *originalFunctionPtr = (long*) originalFunctionAddress;
|
||||
mach_error_t err = err_none;
|
||||
|
||||
#if defined(__ppc__) || defined(__POWERPC__)
|
||||
// Ensure first instruction isn't 'mfctr'.
|
||||
#define kMFCTRMask 0xfc1fffff
|
||||
#define kMFCTRInstruction 0x7c0903a6
|
||||
|
||||
long originalInstruction = *originalFunctionPtr;
|
||||
if( !err && ((originalInstruction & kMFCTRMask) == kMFCTRInstruction) )
|
||||
err = err_cannot_override;
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
int eatenCount = 0;
|
||||
int originalInstructionCount = 0;
|
||||
char originalInstructions[kOriginalInstructionsSize];
|
||||
uint8_t originalInstructionSizes[kOriginalInstructionsSize];
|
||||
uint64_t jumpRelativeInstruction = 0; // JMP
|
||||
|
||||
Boolean overridePossible = eatKnownInstructions ((unsigned char *)originalFunctionPtr,
|
||||
&jumpRelativeInstruction, &eatenCount,
|
||||
originalInstructions, &originalInstructionCount,
|
||||
originalInstructionSizes );
|
||||
if (eatenCount + kMaxFixupSizeIncrease > kOriginalInstructionsSize) {
|
||||
//printf ("Too many instructions eaten\n");
|
||||
overridePossible = false;
|
||||
}
|
||||
if (!overridePossible) err = err_cannot_override;
|
||||
if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
|
||||
#endif
|
||||
|
||||
// Make the original function implementation writable.
|
||||
if( !err ) {
|
||||
err = vm_protect( mach_task_self(),
|
||||
(vm_address_t) originalFunctionPtr, 8, false,
|
||||
(VM_PROT_ALL | VM_PROT_COPY) );
|
||||
if( err )
|
||||
err = vm_protect( mach_task_self(),
|
||||
(vm_address_t) originalFunctionPtr, 8, false,
|
||||
(VM_PROT_DEFAULT | VM_PROT_COPY) );
|
||||
}
|
||||
if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
|
||||
|
||||
// Allocate and target the escape island to the overriding function.
|
||||
BranchIsland *escapeIsland = NULL;
|
||||
if( !err )
|
||||
err = allocateBranchIsland( &escapeIsland, originalFunctionAddress );
|
||||
if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
|
||||
|
||||
|
||||
#if defined(__ppc__) || defined(__POWERPC__)
|
||||
if( !err )
|
||||
err = setBranchIslandTarget( escapeIsland, overrideFunctionAddress, 0 );
|
||||
|
||||
// Build the branch absolute instruction to the escape island.
|
||||
long branchAbsoluteInstruction = 0; // Set to 0 just to silence warning.
|
||||
if( !err ) {
|
||||
long escapeIslandAddress = ((long) escapeIsland) & 0x3FFFFFF;
|
||||
branchAbsoluteInstruction = 0x48000002 | escapeIslandAddress;
|
||||
}
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
|
||||
|
||||
if( !err )
|
||||
err = setBranchIslandTarget_i386( escapeIsland, overrideFunctionAddress, 0 );
|
||||
|
||||
if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
|
||||
// Build the jump relative instruction to the escape island
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (!err) {
|
||||
uint32_t addressOffset = ((char*)escapeIsland - (char*)originalFunctionPtr - 5);
|
||||
addressOffset = OSSwapInt32(addressOffset);
|
||||
|
||||
jumpRelativeInstruction |= 0xE900000000000000LL;
|
||||
jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff) << 24;
|
||||
jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Optionally allocate & return the reentry island. This may contain relocated
|
||||
// jmp instructions and so has all the same addressing reachability requirements
|
||||
// the escape island has to the original function, except the escape island is
|
||||
// technically our original function.
|
||||
BranchIsland *reentryIsland = NULL;
|
||||
if( !err && originalFunctionReentryIsland ) {
|
||||
err = allocateBranchIsland( &reentryIsland, escapeIsland);
|
||||
if( !err )
|
||||
*originalFunctionReentryIsland = reentryIsland;
|
||||
}
|
||||
|
||||
#if defined(__ppc__) || defined(__POWERPC__)
|
||||
// Atomically:
|
||||
// o If the reentry island was allocated:
|
||||
// o Insert the original instruction into the reentry island.
|
||||
// o Target the reentry island at the 2nd instruction of the
|
||||
// original function.
|
||||
// o Replace the original instruction with the branch absolute.
|
||||
if( !err ) {
|
||||
int escapeIslandEngaged = false;
|
||||
do {
|
||||
if( reentryIsland )
|
||||
err = setBranchIslandTarget( reentryIsland,
|
||||
(void*) (originalFunctionPtr+1), originalInstruction );
|
||||
if( !err ) {
|
||||
escapeIslandEngaged = CompareAndSwap( originalInstruction,
|
||||
branchAbsoluteInstruction,
|
||||
(UInt32*)originalFunctionPtr );
|
||||
if( !escapeIslandEngaged ) {
|
||||
// Someone replaced the instruction out from under us,
|
||||
// re-read the instruction, make sure it's still not
|
||||
// 'mfctr' and try again.
|
||||
originalInstruction = *originalFunctionPtr;
|
||||
if( (originalInstruction & kMFCTRMask) == kMFCTRInstruction)
|
||||
err = err_cannot_override;
|
||||
}
|
||||
}
|
||||
} while( !err && !escapeIslandEngaged );
|
||||
}
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
// Atomically:
|
||||
// o If the reentry island was allocated:
|
||||
// o Insert the original instructions into the reentry island.
|
||||
// o Target the reentry island at the first non-replaced
|
||||
// instruction of the original function.
|
||||
// o Replace the original first instructions with the jump relative.
|
||||
//
|
||||
// Note that on i386, we do not support someone else changing the code under our feet
|
||||
if ( !err ) {
|
||||
uint32_t offset = (uintptr_t)originalFunctionPtr - (uintptr_t)reentryIsland;
|
||||
fixupInstructions(offset, originalInstructions,
|
||||
originalInstructionCount, originalInstructionSizes );
|
||||
|
||||
if( reentryIsland )
|
||||
err = setBranchIslandTarget_i386( reentryIsland,
|
||||
(void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions );
|
||||
// try making islands executable before planting the jmp
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
if( !err )
|
||||
err = makeIslandExecutable(escapeIsland);
|
||||
if( !err && reentryIsland )
|
||||
err = makeIslandExecutable(reentryIsland);
|
||||
#endif
|
||||
if ( !err )
|
||||
atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelativeInstruction);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Clean up on error.
|
||||
if( err ) {
|
||||
if( reentryIsland )
|
||||
freeBranchIsland( reentryIsland );
|
||||
if( escapeIsland )
|
||||
freeBranchIsland( escapeIsland );
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Implementation
|
||||
*
|
||||
*******************************************************************************/
|
||||
#pragma mark -
|
||||
#pragma mark (Implementation)
|
||||
|
||||
static bool jump_in_range(intptr_t from, intptr_t to) {
|
||||
intptr_t field_value = to - from - 5;
|
||||
int32_t field_value_32 = field_value;
|
||||
return field_value == field_value_32;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Implementation: Allocates memory for a branch island.
|
||||
|
||||
@param island <- The allocated island.
|
||||
@result <- mach_error_t
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
static mach_error_t
|
||||
allocateBranchIslandAux(
|
||||
BranchIsland **island,
|
||||
void *originalFunctionAddress,
|
||||
bool forward)
|
||||
{
|
||||
assert( island );
|
||||
assert( sizeof( BranchIsland ) <= kPageSize );
|
||||
|
||||
vm_map_t task_self = mach_task_self();
|
||||
vm_address_t original_address = (vm_address_t) originalFunctionAddress;
|
||||
vm_address_t address = original_address;
|
||||
|
||||
for (;;) {
|
||||
vm_size_t vmsize = 0;
|
||||
memory_object_name_t object = 0;
|
||||
kern_return_t kr = 0;
|
||||
vm_region_flavor_t flavor = VM_REGION_BASIC_INFO;
|
||||
// Find the region the address is in.
|
||||
#if __WORDSIZE == 32
|
||||
vm_region_basic_info_data_t info;
|
||||
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
|
||||
kr = vm_region(task_self, &address, &vmsize, flavor,
|
||||
(vm_region_info_t)&info, &info_count, &object);
|
||||
#else
|
||||
vm_region_basic_info_data_64_t info;
|
||||
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
|
||||
kr = vm_region_64(task_self, &address, &vmsize, flavor,
|
||||
(vm_region_info_t)&info, &info_count, &object);
|
||||
#endif
|
||||
if (kr != KERN_SUCCESS)
|
||||
return kr;
|
||||
assert((address & (kPageSize - 1)) == 0);
|
||||
|
||||
// Go to the first page before or after this region
|
||||
vm_address_t new_address = forward ? address + vmsize : address - kPageSize;
|
||||
#if __WORDSIZE == 64
|
||||
if(!jump_in_range(original_address, new_address))
|
||||
break;
|
||||
#endif
|
||||
address = new_address;
|
||||
|
||||
// Try to allocate this page.
|
||||
kr = vm_allocate(task_self, &address, kPageSize, 0);
|
||||
if (kr == KERN_SUCCESS) {
|
||||
*island = (BranchIsland*) address;
|
||||
return err_none;
|
||||
}
|
||||
if (kr != KERN_NO_SPACE)
|
||||
return kr;
|
||||
}
|
||||
|
||||
return KERN_NO_SPACE;
|
||||
}
|
||||
|
||||
static mach_error_t
|
||||
allocateBranchIsland(
|
||||
BranchIsland **island,
|
||||
void *originalFunctionAddress)
|
||||
{
|
||||
mach_error_t err =
|
||||
allocateBranchIslandAux(island, originalFunctionAddress, true);
|
||||
if (!err)
|
||||
return err;
|
||||
return allocateBranchIslandAux(island, originalFunctionAddress, false);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
Implementation: Deallocates memory for a branch island.
|
||||
|
||||
@param island -> The island to deallocate.
|
||||
@result <- mach_error_t
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
mach_error_t
|
||||
freeBranchIsland(
|
||||
BranchIsland *island )
|
||||
{
|
||||
assert( island );
|
||||
assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] );
|
||||
assert( sizeof( BranchIsland ) <= kPageSize );
|
||||
return vm_deallocate( mach_task_self(), (vm_address_t) island,
|
||||
kPageSize );
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Implementation: Sets the branch island's target, with an optional
|
||||
instruction.
|
||||
|
||||
@param island -> The branch island to insert target into.
|
||||
@param branchTo -> The address of the target.
|
||||
@param instruction -> Optional instruction to execute prior to branch. Set
|
||||
to zero for nop.
|
||||
@result <- mach_error_t
|
||||
|
||||
***************************************************************************/
|
||||
#if defined(__ppc__) || defined(__POWERPC__)
|
||||
mach_error_t
|
||||
setBranchIslandTarget(
|
||||
BranchIsland *island,
|
||||
const void *branchTo,
|
||||
long instruction )
|
||||
{
|
||||
// Copy over the template code.
|
||||
bcopy( kIslandTemplate, island->instructions, sizeof( kIslandTemplate ) );
|
||||
|
||||
// Fill in the address.
|
||||
((short*)island->instructions)[kAddressLo] = ((long) branchTo) & 0x0000FFFF;
|
||||
((short*)island->instructions)[kAddressHi]
|
||||
= (((long) branchTo) >> 16) & 0x0000FFFF;
|
||||
|
||||
// Fill in the (optional) instuction.
|
||||
if( instruction != 0 ) {
|
||||
((short*)island->instructions)[kInstructionLo]
|
||||
= instruction & 0x0000FFFF;
|
||||
((short*)island->instructions)[kInstructionHi]
|
||||
= (instruction >> 16) & 0x0000FFFF;
|
||||
}
|
||||
|
||||
//MakeDataExecutable( island->instructions, sizeof( kIslandTemplate ) );
|
||||
msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE );
|
||||
|
||||
return err_none;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
mach_error_t
|
||||
setBranchIslandTarget_i386(
|
||||
BranchIsland *island,
|
||||
const void *branchTo,
|
||||
char* instructions )
|
||||
{
|
||||
|
||||
// Copy over the template code.
|
||||
bcopy( kIslandTemplate, island->instructions, sizeof( kIslandTemplate ) );
|
||||
|
||||
// copy original instructions
|
||||
if (instructions) {
|
||||
bcopy (instructions, island->instructions + kInstructions, kOriginalInstructionsSize);
|
||||
}
|
||||
|
||||
// Fill in the address.
|
||||
int32_t addressOffset = (char *)branchTo - (island->instructions + kJumpAddress + 4);
|
||||
*((int32_t *)(island->instructions + kJumpAddress)) = addressOffset;
|
||||
|
||||
msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE );
|
||||
return err_none;
|
||||
}
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
mach_error_t
|
||||
setBranchIslandTarget_i386(
|
||||
BranchIsland *island,
|
||||
const void *branchTo,
|
||||
char* instructions )
|
||||
{
|
||||
// Copy over the template code.
|
||||
bcopy( kIslandTemplate, island->instructions, sizeof( kIslandTemplate ) );
|
||||
|
||||
// Copy original instructions.
|
||||
if (instructions) {
|
||||
bcopy (instructions, island->instructions, kOriginalInstructionsSize);
|
||||
}
|
||||
|
||||
// Fill in the address.
|
||||
*((uint64_t *)(island->instructions + kJumpAddress)) = (uint64_t)branchTo;
|
||||
msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE );
|
||||
|
||||
return err_none;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
// simplistic instruction matching
|
||||
typedef struct {
|
||||
unsigned int length; // max 15
|
||||
unsigned char mask[15]; // sequence of bytes in memory order
|
||||
unsigned char constraint[15]; // sequence of bytes in memory order
|
||||
} AsmInstructionMatch;
|
||||
|
||||
#if defined(__i386__)
|
||||
static AsmInstructionMatch possibleInstructions[] = {
|
||||
{ 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x????????
|
||||
{ 0x5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x55, 0x89, 0xe5, 0xc9, 0xc3} }, // push %ebp; mov %esp,%ebp; leave; ret
|
||||
{ 0x1, {0xFF}, {0x90} }, // nop
|
||||
{ 0x1, {0xFF}, {0x55} }, // push %esp
|
||||
{ 0x2, {0xFF, 0xFF}, {0x89, 0xE5} }, // mov %esp,%ebp
|
||||
{ 0x1, {0xFF}, {0x53} }, // push %ebx
|
||||
{ 0x3, {0xFF, 0xFF, 0x00}, {0x83, 0xEC, 0x00} }, // sub 0x??, %esp
|
||||
{ 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x81, 0xEC, 0x00, 0x00, 0x00, 0x00} }, // sub 0x??, %esp with 32bit immediate
|
||||
{ 0x1, {0xFF}, {0x57} }, // push %edi
|
||||
{ 0x1, {0xFF}, {0x56} }, // push %esi
|
||||
{ 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax
|
||||
{ 0x3, {0xFF, 0x4F, 0x00}, {0x8B, 0x45, 0x00} }, // mov $imm(%ebp), %reg
|
||||
{ 0x3, {0xFF, 0x4C, 0x00}, {0x8B, 0x40, 0x00} }, // mov $imm(%eax-%edx), %reg
|
||||
{ 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x8B, 0x4C, 0x24, 0x00} }, // mov $imm(%esp), %ecx
|
||||
{ 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %eax
|
||||
{ 0x6, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0xE8, 0x00, 0x00, 0x00, 0x00, 0x58} }, // call $imm; pop %eax
|
||||
{ 0x0 }
|
||||
};
|
||||
#elif defined(__x86_64__)
|
||||
static AsmInstructionMatch possibleInstructions[] = {
|
||||
{ 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x????????
|
||||
{ 0x1, {0xFF}, {0x90} }, // nop
|
||||
{ 0x1, {0xF8}, {0x50} }, // push %rX
|
||||
{ 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp
|
||||
{ 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp
|
||||
{ 0x4, {0xFB, 0xFF, 0x00, 0x00}, {0x48, 0x89, 0x00, 0x00} }, // move onto rbp
|
||||
{ 0x4, {0xFF, 0xFF, 0xFF, 0xFF}, {0x40, 0x0f, 0xbe, 0xce} }, // movsbl %sil, %ecx
|
||||
{ 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX
|
||||
{ 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX
|
||||
{ 0x5, {0xF8, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %reg
|
||||
{ 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi)
|
||||
{ 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax
|
||||
{ 0x2, {0xFF, 0xFF}, {0x89, 0xF8} }, // mov %edi, %eax
|
||||
|
||||
//leaq offset(%rip),%rax
|
||||
{ 0x7, {0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x48, 0x8d, 0x05, 0x00, 0x00, 0x00, 0x00} },
|
||||
|
||||
{ 0x0 }
|
||||
};
|
||||
#endif
|
||||
|
||||
static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch* instruction)
|
||||
{
|
||||
Boolean match = true;
|
||||
|
||||
size_t i;
|
||||
for (i=0; i<instruction->length; i++) {
|
||||
unsigned char mask = instruction->mask[i];
|
||||
unsigned char constraint = instruction->constraint[i];
|
||||
unsigned char codeValue = code[i];
|
||||
|
||||
match = ((codeValue & mask) == constraint);
|
||||
if (!match) break;
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
static Boolean
|
||||
eatKnownInstructions(
|
||||
unsigned char *code,
|
||||
uint64_t *newInstruction,
|
||||
int *howManyEaten,
|
||||
char *originalInstructions,
|
||||
int *originalInstructionCount,
|
||||
uint8_t *originalInstructionSizes )
|
||||
{
|
||||
Boolean allInstructionsKnown = true;
|
||||
int totalEaten = 0;
|
||||
unsigned char* ptr = code;
|
||||
int remainsToEat = 5; // a JMP instruction takes 5 bytes
|
||||
int instructionIndex = 0;
|
||||
|
||||
if (howManyEaten) *howManyEaten = 0;
|
||||
if (originalInstructionCount) *originalInstructionCount = 0;
|
||||
while (remainsToEat > 0) {
|
||||
Boolean curInstructionKnown = false;
|
||||
|
||||
// See if instruction matches one we know
|
||||
AsmInstructionMatch* curInstr = possibleInstructions;
|
||||
do {
|
||||
if ((curInstructionKnown = codeMatchesInstruction(ptr, curInstr))) break;
|
||||
curInstr++;
|
||||
} while (curInstr->length > 0);
|
||||
|
||||
// if all instruction matches failed, we don't know current instruction then, stop here
|
||||
if (!curInstructionKnown) {
|
||||
allInstructionsKnown = false;
|
||||
fprintf(stderr, "mach_override: some instructions unknown! Need to update mach_override.c\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// At this point, we've matched curInstr
|
||||
int eaten = curInstr->length;
|
||||
ptr += eaten;
|
||||
remainsToEat -= eaten;
|
||||
totalEaten += eaten;
|
||||
|
||||
if (originalInstructionSizes) originalInstructionSizes[instructionIndex] = eaten;
|
||||
instructionIndex += 1;
|
||||
if (originalInstructionCount) *originalInstructionCount = instructionIndex;
|
||||
}
|
||||
|
||||
|
||||
if (howManyEaten) *howManyEaten = totalEaten;
|
||||
|
||||
if (originalInstructions) {
|
||||
Boolean enoughSpaceForOriginalInstructions = (totalEaten < kOriginalInstructionsSize);
|
||||
|
||||
if (enoughSpaceForOriginalInstructions) {
|
||||
memset(originalInstructions, 0x90 /* NOP */, kOriginalInstructionsSize); // fill instructions with NOP
|
||||
bcopy(code, originalInstructions, totalEaten);
|
||||
} else {
|
||||
// printf ("Not enough space in island to store original instructions. Adapt the island definition and kOriginalInstructionsSize\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (allInstructionsKnown) {
|
||||
// save last 3 bytes of first 64bits of codre we'll replace
|
||||
uint64_t currentFirst64BitsOfCode = *((uint64_t *)code);
|
||||
currentFirst64BitsOfCode = OSSwapInt64(currentFirst64BitsOfCode); // back to memory representation
|
||||
currentFirst64BitsOfCode &= 0x0000000000FFFFFFLL;
|
||||
|
||||
// keep only last 3 instructions bytes, first 5 will be replaced by JMP instr
|
||||
*newInstruction &= 0xFFFFFFFFFF000000LL; // clear last 3 bytes
|
||||
*newInstruction |= (currentFirst64BitsOfCode & 0x0000000000FFFFFFLL); // set last 3 bytes
|
||||
}
|
||||
|
||||
return allInstructionsKnown;
|
||||
}
|
||||
|
||||
static void
|
||||
fixupInstructions(
|
||||
uint32_t offset,
|
||||
void *instructionsToFix,
|
||||
int instructionCount,
|
||||
uint8_t *instructionSizes )
|
||||
{
|
||||
// The start of "leaq offset(%rip),%rax"
|
||||
static const uint8_t LeaqHeader[] = {0x48, 0x8d, 0x05};
|
||||
|
||||
int index;
|
||||
for (index = 0;index < instructionCount;index += 1)
|
||||
{
|
||||
if (*(uint8_t*)instructionsToFix == 0xE9) // 32-bit jump relative
|
||||
{
|
||||
uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instructionsToFix + 1);
|
||||
*jumpOffsetPtr += offset;
|
||||
}
|
||||
|
||||
// leaq offset(%rip),%rax
|
||||
if (memcmp(instructionsToFix, LeaqHeader, 3) == 0) {
|
||||
uint32_t *LeaqOffsetPtr = (uint32_t*)((uintptr_t)instructionsToFix + 3);
|
||||
*LeaqOffsetPtr += offset;
|
||||
}
|
||||
|
||||
// 32-bit call relative to the next addr; pop %eax
|
||||
if (*(uint8_t*)instructionsToFix == 0xE8)
|
||||
{
|
||||
// Just this call is larger than the jump we use, so we
|
||||
// know this is the last instruction.
|
||||
assert(index == (instructionCount - 1));
|
||||
assert(instructionSizes[index] == 6);
|
||||
|
||||
// Insert "addl $offset, %eax" in the end so that when
|
||||
// we jump to the rest of the function %eax has the
|
||||
// value it would have if eip had been pushed by the
|
||||
// call in its original position.
|
||||
uint8_t *op = (uint8_t*)instructionsToFix;
|
||||
op += 6;
|
||||
*op = 0x05; // addl
|
||||
uint32_t *addImmPtr = (uint32_t*)(op + 1);
|
||||
*addImmPtr = offset;
|
||||
}
|
||||
|
||||
instructionsToFix = (void*)((uintptr_t)instructionsToFix + instructionSizes[index]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__i386__)
|
||||
void atomic_mov64(
|
||||
uint64_t *targetAddress,
|
||||
uint64_t value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint64_t old_value = *targetAddress;
|
||||
if (OSAtomicCompareAndSwap64(old_value, value, (int64_t*)targetAddress)) return;
|
||||
}
|
||||
}
|
||||
#elif defined(__x86_64__)
|
||||
void atomic_mov64(
|
||||
uint64_t *targetAddress,
|
||||
uint64_t value )
|
||||
{
|
||||
*targetAddress = value;
|
||||
}
|
||||
#endif
|
||||
#endif
|
76
togles/linuxwin/mach_override.h
Normal file
76
togles/linuxwin/mach_override.h
Normal file
@ -0,0 +1,76 @@
|
||||
// mach_override.h semver:1.2.0
|
||||
// Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com
|
||||
// Some rights reserved: http://opensource.org/licenses/mit
|
||||
// https://github.com/rentzsch/mach_override
|
||||
|
||||
#ifndef _mach_override_
|
||||
#define _mach_override_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <mach/error.h>
|
||||
|
||||
#define err_cannot_override (err_local|1)
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/****************************************************************************************
|
||||
Dynamically overrides the function implementation referenced by
|
||||
originalFunctionAddress with the implentation pointed to by overrideFunctionAddress.
|
||||
Optionally returns a pointer to a "reentry island" which, if jumped to, will resume
|
||||
the original implementation.
|
||||
|
||||
@param originalFunctionAddress -> Required address of the function to
|
||||
override (with overrideFunctionAddress).
|
||||
@param overrideFunctionAddress -> Required address to the overriding
|
||||
function.
|
||||
@param originalFunctionReentryIsland <- Optional pointer to pointer to the
|
||||
reentry island. Can be NULL.
|
||||
@result <- err_cannot_override if the original
|
||||
function's implementation begins with
|
||||
the 'mfctr' instruction.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
mach_error_t
|
||||
mach_override_ptr(
|
||||
void *originalFunctionAddress,
|
||||
const void *overrideFunctionAddress,
|
||||
void **originalFunctionReentryIsland );
|
||||
|
||||
__END_DECLS
|
||||
|
||||
/****************************************************************************************
|
||||
If you're using C++ this macro will ease the tedium of typedef'ing, naming, keeping
|
||||
track of reentry islands and defining your override code. See test_mach_override.cp
|
||||
for example usage.
|
||||
|
||||
************************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define MACH_OVERRIDE( ORIGINAL_FUNCTION_RETURN_TYPE, ORIGINAL_FUNCTION_NAME, ORIGINAL_FUNCTION_ARGS, ERR ) \
|
||||
{ \
|
||||
static ORIGINAL_FUNCTION_RETURN_TYPE (*ORIGINAL_FUNCTION_NAME##_reenter)ORIGINAL_FUNCTION_ARGS; \
|
||||
static bool ORIGINAL_FUNCTION_NAME##_overriden = false; \
|
||||
class mach_override_class__##ORIGINAL_FUNCTION_NAME { \
|
||||
public: \
|
||||
static kern_return_t override(void *originalFunctionPtr) { \
|
||||
kern_return_t result = err_none; \
|
||||
if (!ORIGINAL_FUNCTION_NAME##_overriden) { \
|
||||
ORIGINAL_FUNCTION_NAME##_overriden = true; \
|
||||
result = mach_override_ptr( (void*)originalFunctionPtr, \
|
||||
(void*)mach_override_class__##ORIGINAL_FUNCTION_NAME::replacement, \
|
||||
(void**)&ORIGINAL_FUNCTION_NAME##_reenter ); \
|
||||
} \
|
||||
return result; \
|
||||
} \
|
||||
static ORIGINAL_FUNCTION_RETURN_TYPE replacement ORIGINAL_FUNCTION_ARGS {
|
||||
|
||||
#define END_MACH_OVERRIDE( ORIGINAL_FUNCTION_NAME ) \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
err = mach_override_class__##ORIGINAL_FUNCTION_NAME::override((void*)ORIGINAL_FUNCTION_NAME); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _mach_override_
|
116
togles/togl.vpc
Normal file
116
togles/togl.vpc
Normal file
@ -0,0 +1,116 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// TOGL.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR ".." [$WIN32]
|
||||
$Macro SRCDIR ".." [!$WIN32]
|
||||
$Macro OUTBINDIR $LIBPUBLIC
|
||||
$Macro OUTBINNAME "togl"
|
||||
$Macro TOGL_SRCDIR "$SRCDIR/togl/linuxwin"
|
||||
$Macro TOGL_INCDIR "$SRCDIR/public/togl/linuxwin"
|
||||
|
||||
|
||||
$include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
|
||||
// Common Configuration
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE;..\"
|
||||
$PreprocessorDefinitions "$BASE;TOGL_DLL_EXPORT;PROTECTED_THINGS_ENABLE;strncpy=use_Q_strncpy_instead;_snprintf=use_Q_snprintf_instead" [!$OSXALL]
|
||||
$PreprocessorDefinitions "$BASE;TOGL_DLL_EXPORT" [$OSXALL]
|
||||
|
||||
}
|
||||
|
||||
$Linker
|
||||
{
|
||||
$ImportLibrary "$LIBPUBLIC\$_IMPLIB_PREFIX$OUTBINNAME$_IMPLIB_EXT" [!$X360 && !$OSXALL]
|
||||
$ImportLibrary "$SRCDIR\lib\$PLATFORM\$_IMPLIB_PREFIX$OUTBINNAME$_IMPLIB_EXT" [$OSXALL]
|
||||
}
|
||||
|
||||
$Linker [$OSXALL]
|
||||
{
|
||||
$SystemFrameworks "Carbon;OpenGL;Quartz;Cocoa;IOKit"
|
||||
}
|
||||
|
||||
// togl/tier0/vstdlib traditionally used "lib" prefix though nobody else seems to.
|
||||
$Linker [$POSIX]
|
||||
{
|
||||
$OutputFile "$(OBJ_DIR)/$_IMPLIB_PREFIX$OUTBINNAME$_DLL_EXT"
|
||||
}
|
||||
|
||||
$General [$POSIX]
|
||||
{
|
||||
$GameOutputFile "$OUTBINDIR/$_IMPLIB_PREFIX$OUTBINNAME$_DLL_EXT"
|
||||
}
|
||||
|
||||
$PreLinkEvent [$WINDOWS]
|
||||
{
|
||||
$CommandLine "call $SRCDIR\vpc_scripts\valve_p4_edit.cmd $LIBPUBLIC\$(TargetName).lib $SRCDIR" "\n" \
|
||||
"$BASE"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "togl"
|
||||
{
|
||||
$Folder "Source Files" [$GL]
|
||||
{
|
||||
$File "$TOGL_SRCDIR/dx9asmtogl2.cpp"
|
||||
$File "$TOGL_SRCDIR/dxabstract.cpp"
|
||||
$File "$TOGL_SRCDIR/glentrypoints.cpp"
|
||||
$File "$TOGL_SRCDIR/glmgr.cpp"
|
||||
$File "$TOGL_SRCDIR/glmgrbasics.cpp"
|
||||
$File "$TOGL_SRCDIR/glmgrcocoa.mm" [$OSXALL]
|
||||
$File "$TOGL_SRCDIR/intelglmallocworkaround.cpp" [$OSXALL]
|
||||
$File "$TOGL_SRCDIR/mach_override.c" [$OSXALL]
|
||||
$File "$TOGL_SRCDIR/cglmtex.cpp"
|
||||
$File "$TOGL_SRCDIR/cglmfbo.cpp"
|
||||
$File "$TOGL_SRCDIR/cglmprogram.cpp"
|
||||
$File "$TOGL_SRCDIR/cglmbuffer.cpp"
|
||||
$File "$TOGL_SRCDIR/cglmquery.cpp"
|
||||
$File "$TOGL_SRCDIR/asanstubs.cpp"
|
||||
}
|
||||
|
||||
$Folder "DirectX Header Files" [$WIN32 && !$GL]
|
||||
{
|
||||
}
|
||||
|
||||
$Folder "Header Files" [$GL]
|
||||
{
|
||||
$File "$TOGL_SRCDIR/dx9asmtogl2.h"
|
||||
$File "$TOGL_SRCDIR/glmgr_flush.inl"
|
||||
$File "$TOGL_SRCDIR/intelglmallocworkaround.h" [$OSXALL]
|
||||
$File "$TOGL_SRCDIR/mach_override.h" [$OSXALL]
|
||||
}
|
||||
|
||||
$Folder "Public Header Files" [$GL]
|
||||
{
|
||||
$File "$SRCDIR/public/togl/rendermechanism.h"
|
||||
$File "$TOGL_INCDIR/dxabstract.h"
|
||||
$File "$TOGL_INCDIR/dxabstract_types.h"
|
||||
$File "$TOGL_INCDIR/glbase.h"
|
||||
$File "$TOGL_INCDIR/glentrypoints.h"
|
||||
$File "$TOGL_INCDIR/glmgr.h"
|
||||
$File "$TOGL_INCDIR/glmdebug.h"
|
||||
$File "$TOGL_INCDIR/glmgrbasics.h"
|
||||
$File "$TOGL_INCDIR/glmgrext.h"
|
||||
$File "$TOGL_INCDIR/glmdisplay.h"
|
||||
$File "$TOGL_INCDIR/glmdisplaydb.h"
|
||||
$File "$TOGL_INCDIR/glfuncs.h"
|
||||
$File "$TOGL_INCDIR/cglmtex.h"
|
||||
$File "$TOGL_INCDIR/cglmfbo.h"
|
||||
$File "$TOGL_INCDIR/cglmprogram.h"
|
||||
$File "$TOGL_INCDIR/cglmbuffer.h"
|
||||
$File "$TOGL_INCDIR/cglmquery.h"
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib tier2
|
||||
$Lib mathlib
|
||||
}
|
||||
}
|
||||
|
62
togles/wscript
Executable file
62
togles/wscript
Executable file
@ -0,0 +1,62 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from waflib import Utils
|
||||
import os
|
||||
|
||||
top = '.'
|
||||
PROJECT_NAME = 'togl'
|
||||
|
||||
def options(opt):
|
||||
# stub
|
||||
return
|
||||
|
||||
def configure(conf):
|
||||
conf.define('TOGL_DLL_EXPORT',1)
|
||||
conf.env.append_unique('DEFINES',['strncpy=use_Q_strncpy_instead',
|
||||
'_snprintf=use_Q_snprintf_instead'])
|
||||
|
||||
def build(bld):
|
||||
source = [
|
||||
'linuxwin/dx9asmtogl2.cpp',
|
||||
'linuxwin/dxabstract.cpp',
|
||||
'linuxwin/glentrypoints.cpp',
|
||||
'linuxwin/glmgr.cpp',
|
||||
'linuxwin/glmgrbasics.cpp',
|
||||
#'linuxwin/glmgrcocoa.mm', [$OSXALL]
|
||||
#'linuxwin/intelglmallocworkaround.cpp', [$OSXALL]
|
||||
#'linuxwin/mach_override.c', [$OSXALL]
|
||||
'linuxwin/cglmtex.cpp',
|
||||
'linuxwin/cglmfbo.cpp',
|
||||
'linuxwin/cglmprogram.cpp',
|
||||
'linuxwin/cglmbuffer.cpp',
|
||||
'linuxwin/cglmquery.cpp',
|
||||
'linuxwin/asanstubs.cpp'
|
||||
]
|
||||
|
||||
includes = [
|
||||
'.',
|
||||
'../public',
|
||||
'../public/tier0',
|
||||
'../public/tier1'
|
||||
] + bld.env.INCLUDES_SDL2
|
||||
|
||||
defines = []
|
||||
|
||||
libs = ['tier0','tier1','tier2','vstdlib','mathlib']
|
||||
|
||||
install_path = bld.env.LIBDIR
|
||||
|
||||
bld.shlib(
|
||||
source = source,
|
||||
target = PROJECT_NAME,
|
||||
name = PROJECT_NAME,
|
||||
features = 'c cxx',
|
||||
includes = includes,
|
||||
defines = defines,
|
||||
use = libs,
|
||||
install_path = install_path,
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM,
|
||||
idx = bld.get_taskgen_count()
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user