networking
This commit is contained in:
367
external/steamworks/glmgr/cglmbuffer.cpp
vendored
Normal file
367
external/steamworks/glmgr/cglmbuffer.cpp
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// cglmbuffer.cpp
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#include "glmgr.h"
|
||||
#include "glmdisplay.h"
|
||||
#include "cglmbuffer.h"
|
||||
|
||||
#ifdef OSX
|
||||
// Debugger - 10.8
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
// void BindBufferARB(enum target, uint buffer);
|
||||
// void DeleteBuffersARB(sizei n, const uint *buffers);
|
||||
// void GenBuffersARB(sizei n, uint *buffers);
|
||||
// boolean IsBufferARB(uint buffer);
|
||||
//
|
||||
// void BufferDataARB(enum target, sizeiptrARB size, const void *data,
|
||||
// enum usage);
|
||||
// void BufferSubDataARB(enum target, intptrARB offset, sizeiptrARB size,
|
||||
// const void *data);
|
||||
// void GetBufferSubDataARB(enum target, intptrARB offset,
|
||||
// sizeiptrARB size, void *data);
|
||||
//
|
||||
// void *MapBufferARB(enum target, enum access);
|
||||
// boolean UnmapBufferARB(enum target);
|
||||
//
|
||||
// void GetBufferParameterivARB(enum target, enum pname, int *params);
|
||||
// void GetBufferPointervARB(enum target, enum pname, void **params);
|
||||
//
|
||||
//New Tokens
|
||||
//
|
||||
// Accepted by the <target> parameters of BindBufferARB, BufferDataARB,
|
||||
// BufferSubDataARB, MapBufferARB, UnmapBufferARB,
|
||||
// GetBufferSubDataARB, GetBufferParameterivARB, and
|
||||
// GetBufferPointervARB:
|
||||
//
|
||||
// ARRAY_BUFFER_ARB 0x8892
|
||||
// ELEMENT_ARRAY_BUFFER_ARB 0x8893
|
||||
//
|
||||
// Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
|
||||
// GetFloatv, and GetDoublev:
|
||||
//
|
||||
// ARRAY_BUFFER_BINDING_ARB 0x8894
|
||||
// ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
|
||||
// VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
|
||||
// NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
|
||||
// COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
|
||||
// INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
|
||||
// TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
|
||||
// EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
|
||||
// SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
|
||||
// FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
|
||||
// WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
|
||||
//
|
||||
// Accepted by the <pname> parameter of GetVertexAttribivARB:
|
||||
//
|
||||
// VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
|
||||
//
|
||||
// Accepted by the <usage> parameter of BufferDataARB:
|
||||
//
|
||||
// STREAM_DRAW_ARB 0x88E0
|
||||
// STREAM_READ_ARB 0x88E1
|
||||
// STREAM_COPY_ARB 0x88E2
|
||||
// STATIC_DRAW_ARB 0x88E4
|
||||
// STATIC_READ_ARB 0x88E5
|
||||
// STATIC_COPY_ARB 0x88E6
|
||||
// DYNAMIC_DRAW_ARB 0x88E8
|
||||
// DYNAMIC_READ_ARB 0x88E9
|
||||
// DYNAMIC_COPY_ARB 0x88EA
|
||||
//
|
||||
// Accepted by the <access> parameter of MapBufferARB:
|
||||
//
|
||||
// READ_ONLY_ARB 0x88B8
|
||||
// WRITE_ONLY_ARB 0x88B9
|
||||
// READ_WRITE_ARB 0x88BA
|
||||
//
|
||||
// Accepted by the <pname> parameter of GetBufferParameterivARB:
|
||||
//
|
||||
// BUFFER_SIZE_ARB 0x8764
|
||||
// BUFFER_USAGE_ARB 0x8765
|
||||
// BUFFER_ACCESS_ARB 0x88BB
|
||||
// BUFFER_MAPPED_ARB 0x88BC
|
||||
//
|
||||
// Accepted by the <pname> parameter of GetBufferPointervARB:
|
||||
//
|
||||
// BUFFER_MAP_POINTER_ARB 0x88BD
|
||||
|
||||
// http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt
|
||||
// Accepted by the <target> parameters of BindBuffer, BufferData,
|
||||
// BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData,
|
||||
// GetBufferParameteriv, and GetBufferPointerv:
|
||||
// PIXEL_PACK_BUFFER_ARB 0x88EB
|
||||
// PIXEL_UNPACK_BUFFER_ARB 0x88EC
|
||||
|
||||
|
||||
// gl_bufmode: zero means we mark all vertex/index buffers static
|
||||
|
||||
// non zero means buffers are initially marked static..
|
||||
// ->but can shift to dynamic upon first 'discard' (orphaning)
|
||||
|
||||
//ConVar gl_bufmode( "gl_bufmode", "1" );
|
||||
int gl_bufmode = 1;
|
||||
|
||||
CGLMBuffer::CGLMBuffer( GLMContext *ctx, EGLMBufferType type, uint size, uint options )
|
||||
{
|
||||
m_ctx = ctx;
|
||||
m_type = type;
|
||||
switch(m_type)
|
||||
{
|
||||
case kGLMVertexBuffer: m_buffGLTarget = GL_ARRAY_BUFFER_ARB; break;
|
||||
case kGLMIndexBuffer: m_buffGLTarget = GL_ELEMENT_ARRAY_BUFFER_ARB; break;
|
||||
case kGLMUniformBuffer: m_buffGLTarget = GL_UNIFORM_BUFFER_EXT; break;
|
||||
case kGLMPixelBuffer: m_buffGLTarget = GL_PIXEL_UNPACK_BUFFER_ARB; break;
|
||||
|
||||
default: //Assert(!"Unknown buffer type" );
|
||||
break;
|
||||
}
|
||||
m_size = size;
|
||||
m_bound = false;
|
||||
m_mapped = false;
|
||||
m_lastMappedAddress = NULL;
|
||||
|
||||
m_enableAsyncMap = false;
|
||||
m_enableExplicitFlush = false;
|
||||
m_dirtyMinOffset = m_dirtyMaxOffset = 0; // adjust/grow on lock, clear on unlock
|
||||
|
||||
m_ctx->CheckCurrent();
|
||||
m_revision = rand();
|
||||
|
||||
// make a decision about pseudo mode
|
||||
// this looked like it didn't help much or was actually slower, so leave it available but only as opt-in.
|
||||
// a more clever implementation would be able to select pseudo buf storage for small batches only..
|
||||
m_pseudo = false; // (m_type==kGLMIndexBuffer) && (CommandLine()->FindParm("-gl_enable_pseudobufs"));
|
||||
if (m_pseudo)
|
||||
{
|
||||
m_name = 0;
|
||||
m_pseudoBuf = (char*)malloc( size );
|
||||
|
||||
m_ctx->BindBufferToCtx( m_type, NULL ); // exit with no buffer bound
|
||||
}
|
||||
else
|
||||
{
|
||||
glGenBuffersARB( 1, &m_name );
|
||||
GLMCheckError();
|
||||
|
||||
m_ctx->BindBufferToCtx( m_type, this ); // causes glBindBufferARB
|
||||
|
||||
// buffers start out static, but if they get orphaned and gl_bufmode is non zero,
|
||||
// then they will get flipped to dynamic.
|
||||
|
||||
GLenum hint = GL_STATIC_DRAW_ARB;
|
||||
switch(m_type)
|
||||
{
|
||||
case kGLMVertexBuffer: hint = (options & GLMBufferOptionDynamic) ? GL_DYNAMIC_DRAW_ARB : GL_STATIC_DRAW_ARB; break;
|
||||
case kGLMIndexBuffer: hint = (options & GLMBufferOptionDynamic) ? GL_DYNAMIC_DRAW_ARB : GL_STATIC_DRAW_ARB; break;
|
||||
case kGLMUniformBuffer: hint = GL_DYNAMIC_DRAW_ARB; break; // "fwiw" - shrug
|
||||
case kGLMPixelBuffer: hint = (options & GLMBufferOptionDynamic) ? GL_DYNAMIC_DRAW_ARB : GL_STATIC_DRAW_ARB; break;
|
||||
|
||||
default: //Assert(!"Unknown buffer type" );
|
||||
break;
|
||||
}
|
||||
|
||||
glBufferDataARB( m_buffGLTarget, m_size, NULL, hint ); // may ultimately need more hints to set the usage correctly (esp for streaming)
|
||||
|
||||
this->SetModes( false, true, true );
|
||||
|
||||
m_ctx->BindBufferToCtx( m_type, NULL ); // unbind me
|
||||
}
|
||||
}
|
||||
|
||||
CGLMBuffer::~CGLMBuffer( )
|
||||
{
|
||||
m_ctx->CheckCurrent();
|
||||
|
||||
if (m_pseudo)
|
||||
{
|
||||
free (m_pseudoBuf);
|
||||
m_pseudoBuf = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
glDeleteBuffersARB( 1, &m_name );
|
||||
GLMCheckError();
|
||||
}
|
||||
|
||||
m_ctx = NULL;
|
||||
m_name = 0;
|
||||
m_bound = 0;
|
||||
|
||||
m_lastMappedAddress = NULL;
|
||||
}
|
||||
|
||||
void CGLMBuffer::SetModes ( bool asyncMap, bool explicitFlush, bool force )
|
||||
{
|
||||
// assumes buffer is bound. called by constructor and by Lock.
|
||||
|
||||
if (m_pseudo)
|
||||
{
|
||||
// ignore it...
|
||||
}
|
||||
else
|
||||
{
|
||||
if (force || (m_enableAsyncMap != asyncMap) )
|
||||
{
|
||||
// note the sense of the parameter, it's TRUE if you *want* serialization, so for async you turn it to false.
|
||||
glBufferParameteriAPPLE( this->m_buffGLTarget, GL_BUFFER_SERIALIZED_MODIFY_APPLE, asyncMap==false );
|
||||
m_enableAsyncMap = asyncMap;
|
||||
}
|
||||
|
||||
if (force || (m_enableExplicitFlush != explicitFlush) )
|
||||
{
|
||||
// note the sense of the parameter, it's TRUE if you *want* auto-flush-on-unmap, so for explicit-flush, you turn it to false.
|
||||
glBufferParameteriAPPLE( this->m_buffGLTarget, GL_BUFFER_FLUSHING_UNMAP_APPLE, explicitFlush==false );
|
||||
m_enableExplicitFlush = explicitFlush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CGLMBuffer::FlushRange ( uint offset, uint size )
|
||||
{
|
||||
if (m_pseudo)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
else
|
||||
{
|
||||
// assumes buffer is bound.
|
||||
glFlushMappedBufferRangeAPPLE(this->m_buffGLTarget, (GLintptr)offset, (GLsizeiptr)size);
|
||||
}
|
||||
}
|
||||
|
||||
//ConVar gl_buffer_alignment_quantum ( "gl_buffer_alignment_quantum", "32" ); // the alignment we use pre-SLGU
|
||||
//ConVar gl_buffer_alignment_quantum_slgu( "gl_buffer_alignment_quantum_slgu", "2" ); // alignment used post-SLGU
|
||||
|
||||
int gl_buffer_alignment_quantum = 32;
|
||||
int gl_buffer_alignment_quantum_slgu = 2;
|
||||
|
||||
void CGLMBuffer::Lock( GLMBuffLockParams *params, char **addressOut )
|
||||
{
|
||||
char *resultPtr = NULL;
|
||||
|
||||
//Assert( !m_mapped);
|
||||
|
||||
m_ctx->CheckCurrent();
|
||||
GLMCheckError();
|
||||
|
||||
if (params->m_offset >= m_size)
|
||||
Debugger();
|
||||
|
||||
if (params->m_offset + params->m_size > m_size)
|
||||
Debugger();
|
||||
|
||||
// bind (yes, even for pseudo - this binds name 0)
|
||||
m_ctx->BindBufferToCtx( this->m_type, this );
|
||||
|
||||
if (m_pseudo)
|
||||
{
|
||||
// discard is a no-op
|
||||
|
||||
// async map modes are a no-op
|
||||
|
||||
// latch last mapped address (silly..)
|
||||
m_lastMappedAddress = (float*)m_pseudoBuf;
|
||||
|
||||
// calc lock address
|
||||
resultPtr = m_pseudoBuf + params->m_offset;
|
||||
|
||||
// dirty range is a no-op
|
||||
}
|
||||
else
|
||||
{
|
||||
// perform discard if requested
|
||||
if (params->m_discard)
|
||||
{
|
||||
// observe gl_bufmode on any orphan event.
|
||||
// if orphaned and bufmode is nonzero, flip it to dynamic.
|
||||
GLenum hint = gl_bufmode /*.GetInt()*/ ? GL_DYNAMIC_DRAW_ARB : GL_STATIC_DRAW_ARB;
|
||||
glBufferDataARB( m_buffGLTarget, m_size, NULL, hint );
|
||||
|
||||
m_lastMappedAddress = NULL;
|
||||
|
||||
m_revision++; // revision grows on orphan event
|
||||
}
|
||||
|
||||
// adjust async map option appropriately, leave explicit flush unchanged
|
||||
this->SetModes( params->m_nonblocking, m_enableExplicitFlush );
|
||||
|
||||
// map
|
||||
char *mapPtr = (char*)glMapBufferARB( this->m_buffGLTarget, GL_READ_WRITE_ARB );
|
||||
|
||||
if (!mapPtr)
|
||||
{
|
||||
Debugger();
|
||||
}
|
||||
|
||||
if (m_lastMappedAddress)
|
||||
{
|
||||
// just check if it moved
|
||||
//Assert (m_lastMappedAddress == (float*)mapPtr);
|
||||
}
|
||||
|
||||
m_lastMappedAddress = (float*)mapPtr;
|
||||
|
||||
// calculate offset location
|
||||
resultPtr = mapPtr + params->m_offset;
|
||||
|
||||
// adjust dirty range
|
||||
if (m_dirtyMinOffset != m_dirtyMaxOffset)
|
||||
{
|
||||
// grow range
|
||||
m_dirtyMinOffset = std::min( m_dirtyMinOffset, params->m_offset );
|
||||
m_dirtyMaxOffset = std::min( m_dirtyMaxOffset, params->m_offset+params->m_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
// set range
|
||||
m_dirtyMinOffset = params->m_offset;
|
||||
m_dirtyMaxOffset = params->m_offset+params->m_size;
|
||||
}
|
||||
|
||||
// pad and clamp dirty range to choice of boundary
|
||||
uint quantum = (m_ctx->Caps().m_hasPerfPackage1) ? gl_buffer_alignment_quantum_slgu /*.GetInt()*/ : gl_buffer_alignment_quantum /*.GetInt()*/ ;
|
||||
uint quantum_mask = quantum - 1;
|
||||
|
||||
m_dirtyMinOffset = m_dirtyMinOffset & (~quantum_mask);
|
||||
m_dirtyMaxOffset = (m_dirtyMaxOffset + quantum_mask) & (~quantum_mask);
|
||||
m_dirtyMaxOffset = std::min( m_dirtyMaxOffset, m_size );
|
||||
}
|
||||
|
||||
m_mapped = true;
|
||||
|
||||
*addressOut = resultPtr;
|
||||
}
|
||||
|
||||
void CGLMBuffer::Unlock( void )
|
||||
{
|
||||
m_ctx->CheckCurrent();
|
||||
|
||||
//Assert (m_mapped);
|
||||
|
||||
if (m_pseudo)
|
||||
{
|
||||
// nothing to do actually
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ctx->BindBufferToCtx( this->m_type, this );
|
||||
|
||||
// time to do explicit flush
|
||||
if (m_enableExplicitFlush)
|
||||
{
|
||||
this->FlushRange( m_dirtyMinOffset, m_dirtyMaxOffset - m_dirtyMinOffset );
|
||||
}
|
||||
|
||||
// clear dirty range no matter what
|
||||
m_dirtyMinOffset = m_dirtyMaxOffset = 0; // adjust/grow on lock, clear on unlock
|
||||
|
||||
glUnmapBuffer( this->m_buffGLTarget );
|
||||
|
||||
}
|
||||
|
||||
m_mapped = false;
|
||||
}
|
||||
91
external/steamworks/glmgr/cglmbuffer.h
vendored
Normal file
91
external/steamworks/glmgr/cglmbuffer.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// cglmprogram.h
|
||||
// GLMgr buffers (index / vertex)
|
||||
// ... maybe add PBO later as well
|
||||
//===============================================================================
|
||||
|
||||
#ifndef CGLMBUFFER_H
|
||||
#define CGLMBUFFER_H
|
||||
|
||||
#pragma once
|
||||
|
||||
// ext links
|
||||
|
||||
// http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// forward declarations
|
||||
|
||||
class GLMContext;
|
||||
|
||||
enum EGLMBufferType
|
||||
{
|
||||
kGLMVertexBuffer,
|
||||
kGLMIndexBuffer,
|
||||
kGLMUniformBuffer, // for bindable uniform
|
||||
kGLMPixelBuffer, // for PBO
|
||||
|
||||
kGLMNumBufferTypes
|
||||
};
|
||||
|
||||
// pass this in "options" to constructor to make a dynamic buffer
|
||||
#define GLMBufferOptionDynamic 0x00000001
|
||||
|
||||
struct GLMBuffLockParams
|
||||
{
|
||||
uint m_offset;
|
||||
uint m_size;
|
||||
bool m_nonblocking;
|
||||
bool m_discard;
|
||||
};
|
||||
|
||||
class CGLMBuffer
|
||||
{
|
||||
|
||||
public:
|
||||
void Lock( GLMBuffLockParams *params, char **addressOut );
|
||||
void Unlock( void );
|
||||
|
||||
//protected:
|
||||
friend class GLMContext; // only GLMContext can make CGLMBuffer objects
|
||||
friend class GLMTester;
|
||||
friend struct IDirect3D9;
|
||||
friend struct IDirect3DDevice9;
|
||||
|
||||
CGLMBuffer ( GLMContext *ctx, EGLMBufferType type, uint size, uint options );
|
||||
~CGLMBuffer ( );
|
||||
|
||||
void SetModes ( bool asyncMap, bool explicitFlush, bool force = false );
|
||||
void FlushRange ( uint offset, uint size );
|
||||
|
||||
GLMContext *m_ctx; // link back to parent context
|
||||
EGLMBufferType m_type;
|
||||
uint m_size;
|
||||
GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB
|
||||
GLuint m_name; // name of this program in the context
|
||||
uint m_revision; // bump anytime the size changes or buffer is orphaned
|
||||
bool m_enableAsyncMap; // mirror of the buffer state
|
||||
bool m_enableExplicitFlush; // mirror of the buffer state
|
||||
|
||||
bool m_bound; // true if bound to context
|
||||
bool m_mapped; // is it currently mapped
|
||||
uint m_dirtyMinOffset; // when equal, range is empty
|
||||
uint m_dirtyMaxOffset;
|
||||
|
||||
float *m_lastMappedAddress;
|
||||
|
||||
// --------------------- pseudo-VBO support below here (explicitly for dynamic index buffers)
|
||||
bool m_pseudo; // true if the m_name is 0, and the backing is plain RAM
|
||||
|
||||
// in pseudo mode, there is just one RAM buffer that acts as the backing.
|
||||
// expectation is that this mode would only be used for dynamic indices.
|
||||
// since indices have to be consumed (copied to command stream) prior to return from a drawing call,
|
||||
// there's no need to do any fencing or multibuffering. orphaning in particular becomes a no-op.
|
||||
|
||||
char *m_pseudoBuf; // storage for pseudo buffer
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
356
external/steamworks/glmgr/cglmfbo.cpp
vendored
Normal file
356
external/steamworks/glmgr/cglmfbo.cpp
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// cglmfbo.cpp
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#include "glmgr.h"
|
||||
#include "cglmfbo.h"
|
||||
// #include "../shaderapidx9/dxabstract.h"
|
||||
|
||||
#ifdef OSX
|
||||
// Debugger - 10.8
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
CGLMFBO::CGLMFBO( GLMContext *ctx )
|
||||
{
|
||||
m_ctx = ctx;
|
||||
m_ctx->CheckCurrent();
|
||||
|
||||
glGenFramebuffersEXT( 1, &m_name );
|
||||
GLMCheckError();
|
||||
|
||||
memset( m_attach, 0, sizeof( m_attach ) );
|
||||
|
||||
m_sizeX = m_sizeY = 0;
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
GLMCheckError();
|
||||
}
|
||||
}
|
||||
|
||||
glDeleteFramebuffersEXT( 1, &m_name );
|
||||
GLMCheckError();
|
||||
|
||||
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
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 hasone, **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->m_rboDirty == 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
|
||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, tex->m_rboName );
|
||||
GLMCheckError();
|
||||
|
||||
// attach the GL_RENDERBUFFER_EXT target to the depth and stencil attach points
|
||||
glFramebufferRenderbufferEXT( fboBindPoint, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tex->m_rboName);
|
||||
GLMCheckError();
|
||||
|
||||
glFramebufferRenderbufferEXT( fboBindPoint, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tex->m_rboName);
|
||||
GLMCheckError();
|
||||
|
||||
// no need to leave the RBO hanging on
|
||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
||||
GLMCheckError();
|
||||
}
|
||||
else
|
||||
{
|
||||
// color attachment (likely 0)
|
||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, tex->m_rboName );
|
||||
GLMCheckError();
|
||||
|
||||
glFramebufferRenderbufferEXT( fboBindPoint, attachIndexGL, GL_RENDERBUFFER_EXT, tex->m_rboName);
|
||||
GLMCheckError();
|
||||
|
||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
||||
GLMCheckError();
|
||||
}
|
||||
tex->m_rboDirty = true;
|
||||
}
|
||||
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
|
||||
|
||||
glFramebufferTexture2DEXT( fboBindPoint, GL_DEPTH_ATTACHMENT_EXT, target, tex->m_texName, params->m_mip );
|
||||
GLMCheckError();
|
||||
|
||||
glFramebufferTexture2DEXT( fboBindPoint, GL_STENCIL_ATTACHMENT_EXT, target, tex->m_texName, params->m_mip );
|
||||
GLMCheckError();
|
||||
}
|
||||
else
|
||||
{
|
||||
glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, target, tex->m_texName, params->m_mip );
|
||||
GLMCheckError();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_3D:
|
||||
{
|
||||
glFramebufferTexture3DEXT( fboBindPoint, attachIndexGL, target, tex->m_texName, params->m_mip, params->m_zslice );
|
||||
GLMCheckError();
|
||||
}
|
||||
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;
|
||||
|
||||
glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, target, tex->m_texName, params->m_mip );
|
||||
GLMCheckError();
|
||||
}
|
||||
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)
|
||||
|
||||
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );
|
||||
GLMCheckError();
|
||||
|
||||
if (attachIndexGL==GL_DEPTH_STENCIL_ATTACHMENT_EXT)
|
||||
{
|
||||
// detach the GL_RENDERBUFFER_EXT target at depth and stencil attach points
|
||||
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
|
||||
GLMCheckError();
|
||||
|
||||
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
|
||||
GLMCheckError();
|
||||
}
|
||||
else
|
||||
{
|
||||
// color attachment (likely 0)
|
||||
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, attachIndexGL, GL_RENDERBUFFER_EXT, 0);
|
||||
GLMCheckError();
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
glFramebufferTexture2DEXT( fboBindPoint, GL_DEPTH_ATTACHMENT_EXT, 0,0,0 );
|
||||
glFramebufferTexture2DEXT( fboBindPoint, GL_STENCIL_ATTACHMENT_EXT, 0,0,0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, 0, 0, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_3D:
|
||||
{
|
||||
glFramebufferTexture3DEXT( fboBindPoint, attachIndexGL, 0, 0, 0, 0 );
|
||||
GLMCheckError();
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_CUBE_MAP:
|
||||
{
|
||||
glFramebufferTexture2DEXT( fboBindPoint, attachIndexGL, 0, 0, 0 );
|
||||
GLMCheckError();
|
||||
}
|
||||
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 = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
switch(status)
|
||||
{
|
||||
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
||||
result = true;
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
result = false;
|
||||
Debugger();
|
||||
/* choose different formats */
|
||||
break;
|
||||
|
||||
default:
|
||||
result = false;
|
||||
Debugger();
|
||||
/* programming error; will fail on all hardware */
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
91
external/steamworks/glmgr/cglmfbo.h
vendored
Normal file
91
external/steamworks/glmgr/cglmfbo.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// cglmfbo.h
|
||||
// GLMgr FBO's (render targets)
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef CGLMFBO_H
|
||||
#define CGLMFBO_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cglmtex.h"
|
||||
|
||||
// good FBO references / recaps
|
||||
// http://www.songho.ca/opengl/gl_fbo.html
|
||||
// http://www.gamedev.net/reference/articles/article2331.asp
|
||||
|
||||
// ext links
|
||||
|
||||
// http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
|
||||
// http://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// tokens not in the SDK headers
|
||||
|
||||
#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT
|
||||
#define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9
|
||||
#endif
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// forward declarations
|
||||
|
||||
class GLMContext;
|
||||
|
||||
// implicitly 16 maximum color attachments possible
|
||||
enum EGLMFBOAttachment {
|
||||
kAttColor0, kAttColor1, kAttColor2, kAttColor3,
|
||||
kAttColor4, kAttColor5, kAttColor6, kAttColor7,
|
||||
kAttColor8, kAttColor9, kAttColor10, kAttColor11,
|
||||
kAttColor12, kAttColor13, kAttColor14, kAttColor15,
|
||||
kAttDepth, kAttStencil, kAttDepthStencil,
|
||||
kAttCount
|
||||
};
|
||||
|
||||
struct GLMFBOTexAttachParams
|
||||
{
|
||||
CGLMTex *m_tex;
|
||||
int m_face; // keep zero if not cube map
|
||||
int m_mip; // keep zero if notmip mapped
|
||||
int m_zslice; // keep zero if not a 3D tex
|
||||
};
|
||||
|
||||
class CGLMFBO
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
protected:
|
||||
friend class GLMContext; // only GLMContext can make CGLMFBO objects
|
||||
friend class GLMTester;
|
||||
friend class CGLMTex;
|
||||
|
||||
friend struct IDirect3D9;
|
||||
friend struct IDirect3DDevice9;
|
||||
|
||||
CGLMFBO( GLMContext *ctx );
|
||||
~CGLMFBO( );
|
||||
|
||||
void TexAttach( GLMFBOTexAttachParams *params, EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT );
|
||||
void TexDetach( EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT );
|
||||
// you can also pass GL_READ_FRAMEBUFFER_EXT or GL_DRAW_FRAMEBUFFER_EXT to selectively bind the receiving FBO to one or the other.
|
||||
|
||||
void TexScrub( CGLMTex *tex );
|
||||
// search and destroy any attachment for the named texture
|
||||
|
||||
bool IsReady( void ); // aka FBO completeness check - ready to draw
|
||||
|
||||
GLMContext *m_ctx; // link back to parent context
|
||||
|
||||
GLuint m_name; // name of this FBO in the context
|
||||
|
||||
GLMFBOTexAttachParams m_attach[ kAttCount ]; // indexed by EGLMFBOAttachment
|
||||
|
||||
int m_sizeX,m_sizeY;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
1448
external/steamworks/glmgr/cglmprogram.cpp
vendored
Normal file
1448
external/steamworks/glmgr/cglmprogram.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
291
external/steamworks/glmgr/cglmprogram.h
vendored
Normal file
291
external/steamworks/glmgr/cglmprogram.h
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// cglmprogram.h
|
||||
// GLMgr programs (ARBVP/ARBfp)
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef CGLMPROGRAM_H
|
||||
#define CGLMPROGRAM_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
// good ARB program references
|
||||
// http://petewarden.com/notes/archives/2005/05/fragment_progra_2.html
|
||||
// http://petewarden.com/notes/archives/2005/06/fragment_progra_3.html
|
||||
|
||||
// ext links
|
||||
|
||||
// http://www.opengl.org/registry/specs/ARB/vertex_program.txt
|
||||
// http://www.opengl.org/registry/specs/ARB/fragment_program.txt
|
||||
// http://www.opengl.org/registry/specs/EXT/gpu_program_parameters.txt
|
||||
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// tokens not in the SDK headers
|
||||
|
||||
//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT
|
||||
// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9
|
||||
//#endif
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// forward declarations
|
||||
|
||||
class GLMContext;
|
||||
class CGLMShaderPair;
|
||||
class CGLMShaderPairCache;
|
||||
|
||||
// CGLMProgram can contain two flavors of the same program, one in assembler, one in GLSL.
|
||||
// these flavors are pretty different in terms of the API's that are used to activate them -
|
||||
// for example, assembler programs can just get bound to the context, whereas GLSL programs
|
||||
// have to be linked. To some extent we try to hide that detail inside GLM.
|
||||
|
||||
// for now, make CGLMProgram a container, it does not set policy or hold a preference as to which
|
||||
// flavor you want to use. GLMContext has to handle that.
|
||||
|
||||
enum EGLMProgramType
|
||||
{
|
||||
kGLMVertexProgram,
|
||||
kGLMFragmentProgram,
|
||||
|
||||
kGLMNumProgramTypes
|
||||
};
|
||||
|
||||
enum EGLMProgramLang
|
||||
{
|
||||
kGLMARB,
|
||||
kGLMGLSL,
|
||||
|
||||
kGLMNumProgramLangs
|
||||
};
|
||||
|
||||
struct GLMShaderDesc
|
||||
{
|
||||
union
|
||||
{
|
||||
GLuint arb; // ARB program object name
|
||||
GLhandleARB glsl; // GLSL shader object handle (void*)
|
||||
} m_object;
|
||||
|
||||
// these can change if shader text is edited
|
||||
bool m_textPresent; // is this flavor(lang) of text present in the buffer?
|
||||
int m_textOffset; // where is it
|
||||
int m_textLength; // how big
|
||||
|
||||
bool m_compiled; // has this text been through a compile attempt
|
||||
bool m_valid; // and if so, was the compile successful
|
||||
|
||||
int m_slowMark; // has it been flagged during a non native draw batch before. increment every time it's slow.
|
||||
|
||||
int m_highWater; // vount of vec4's in the major uniform array ("vc" on vs, "pc" on ps)
|
||||
// written by dxabstract.... gross!
|
||||
};
|
||||
|
||||
GLenum GLMProgTypeToARBEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target
|
||||
GLenum GLMProgTypeToGLSLEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target
|
||||
|
||||
class CGLMProgram
|
||||
{
|
||||
public:
|
||||
friend class CGLMShaderPairCache;
|
||||
friend class CGLMShaderPair;
|
||||
friend class GLMContext; // only GLMContext can make CGLMProgram objects
|
||||
friend class GLMTester;
|
||||
friend 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
|
||||
|
||||
bool CompileActiveSources ( void ); // compile only the flavors that were provided.
|
||||
bool Compile ( EGLMProgramLang lang );
|
||||
bool CheckValidity ( EGLMProgramLang lang );
|
||||
|
||||
void LogSlow ( EGLMProgramLang lang ); // detailed spew when called for first time; one liner or perhaps silence after that
|
||||
|
||||
void GetLabelIndexCombo ( char *labelOut, int labelOutMaxChars, int *indexOut, int *comboOut );
|
||||
void GetComboIndexNameString ( char *stringOut, int stringOutMaxChars ); // mmmmmmmm-nnnnnnnn-filename
|
||||
|
||||
#if GLMDEBUG
|
||||
bool PollForChanges( void ); // check mirror for changes.
|
||||
void ReloadStringFromEditable( void ); // populate m_string from editable item (react to change)
|
||||
bool SyncWithEditable( void );
|
||||
#endif
|
||||
|
||||
//===============================
|
||||
|
||||
// common stuff
|
||||
|
||||
GLMContext *m_ctx; // link back to parent context
|
||||
|
||||
EGLMProgramType m_type; // vertex or pixel
|
||||
|
||||
uint m_serial; // serial number for hashing
|
||||
|
||||
char *m_text; // copy of text passed into constructor. Can change if editable shaders is enabled.
|
||||
// note - it can contain multiple flavors, so use CGLMTextSectioner to scan it and locate them
|
||||
#if GLMDEBUG
|
||||
CGLMEditableTextItem *m_editable; // editable text item for debugging
|
||||
#endif
|
||||
|
||||
GLMShaderDesc m_descs[ kGLMNumProgramLangs ];
|
||||
|
||||
uint m_samplerMask; // (1<<n) mask of sampler active locs, if this is a fragment shader (dxabstract sets this field)
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
struct GLMShaderPairInfo
|
||||
{
|
||||
int m_status; // -1 means req'd index was out of bounds (loop stop..) 0 means not present. 1 means present/active.
|
||||
|
||||
char m_vsName[ 128 ];
|
||||
int m_vsStaticIndex;
|
||||
int m_vsDynamicIndex;
|
||||
|
||||
char m_psName[ 128 ];
|
||||
int m_psStaticIndex;
|
||||
int m_psDynamicIndex;
|
||||
};
|
||||
|
||||
|
||||
class CGLMShaderPair // a container for a linked GLSL shader pair, and metadata obtained post-link
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
friend class CGLMProgram;
|
||||
friend class GLMContext;
|
||||
friend class CGLMShaderPairCache;
|
||||
|
||||
//===============================
|
||||
|
||||
// constructor just sets up a GLSL program object and leaves it empty.
|
||||
CGLMShaderPair( GLMContext *ctx );
|
||||
~CGLMShaderPair( );
|
||||
|
||||
bool SetProgramPair ( CGLMProgram *vp, CGLMProgram *fp );
|
||||
// true result means successful link and query
|
||||
|
||||
bool RefreshProgramPair ( void );
|
||||
// re-link and re-query the uniforms
|
||||
|
||||
//===============================
|
||||
|
||||
// common stuff
|
||||
|
||||
GLMContext *m_ctx; // link back to parent context
|
||||
|
||||
CGLMProgram *m_vertexProg;
|
||||
CGLMProgram *m_fragmentProg;
|
||||
|
||||
GLhandleARB m_program; // linked program object
|
||||
|
||||
// need meta data for attribs / samplers / params
|
||||
// actually we only need it for samplers and params.
|
||||
// attributes are hardwired.
|
||||
|
||||
// vertex stage uniforms
|
||||
GLint m_locVertexParams; // "vc" per dx9asmtogl2 convention
|
||||
GLint m_locVertexInteger0; // "i0"
|
||||
GLint m_locVertexBool0; // "b0"
|
||||
GLint m_locVertexBool1; // "b1"
|
||||
GLint m_locVertexBool2; // "b2"
|
||||
GLint m_locVertexBool3; // "b3"
|
||||
|
||||
// fragment stage uniforms
|
||||
GLint m_locFragmentParams; // "pc" per dx9asmtogl2 convention
|
||||
GLint m_locFragmentFakeSRGBEnable; // "flSRGBWrite" - set to 1.0 to effect sRGB encoding on output
|
||||
float m_fakeSRGBEnableValue; // shadow to avoid redundant sets of the m_locFragmentFakeSRGBEnable uniform
|
||||
// init it to -1.0 at link or relink, so it will trip on any legit incoming value (0.0 or 1.0)
|
||||
|
||||
GLint m_locSamplers[ 16 ]; // "sampler0 ... sampler1..."
|
||||
|
||||
// other stuff
|
||||
bool m_valid; // true on successful link
|
||||
bool m_samplersFixed; // set on first draw (can't write the uniforms until the program is in use, and we don't want to mess with cur program inside cglmprogram)
|
||||
uint m_revision; // if this pair is relinked, bump this number.
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// N-row, M-way associative cache with LRU per row.
|
||||
// still needs some metric dump ability and some parameter tuning.
|
||||
// extra credit would be to make an auto-tuner.
|
||||
|
||||
struct CGLMPairCacheEntry
|
||||
{
|
||||
long long m_lastMark; // a mark of zero means an empty entry
|
||||
CGLMProgram *m_vertexProg;
|
||||
CGLMProgram *m_fragmentProg;
|
||||
uint m_extraKeyBits;
|
||||
CGLMShaderPair *m_pair;
|
||||
};
|
||||
|
||||
class CGLMShaderPairCache // cache for linked GLSL shader pairs
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
protected:
|
||||
friend class CGLMShaderPair;
|
||||
friend class CGLMProgram;
|
||||
friend class GLMContext;
|
||||
|
||||
//===============================
|
||||
|
||||
CGLMShaderPairCache( GLMContext *ctx );
|
||||
~CGLMShaderPairCache( );
|
||||
|
||||
CGLMShaderPair *SelectShaderPair ( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits );
|
||||
void QueryShaderPair ( int index, GLMShaderPairInfo *infoOut );
|
||||
|
||||
// shoot down linked pairs that use the program in the arg
|
||||
// return true if any had to be skipped due to conflict with currently bound pair
|
||||
bool PurgePairsWithShader( CGLMProgram *prog );
|
||||
|
||||
// purge everything (when would GLM know how to do this ? at context destroy time, but any other times?)
|
||||
// return true if any had to be skipped due to conflict with currently bound pair
|
||||
bool Purge ( void );
|
||||
|
||||
// stats
|
||||
void DumpStats ( void );
|
||||
|
||||
//===============================
|
||||
|
||||
uint HashRowIndex ( CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits );
|
||||
CGLMPairCacheEntry* HashRowPtr ( uint hashRowIndex );
|
||||
void HashRowProbe ( CGLMPairCacheEntry *row, CGLMProgram *vp, CGLMProgram *fp, uint extraKeyBits, int *hitwayOut, int *emptywayOut, int *oldestwayOut );
|
||||
//===============================
|
||||
|
||||
// common stuff
|
||||
|
||||
GLMContext *m_ctx; // link back to parent context
|
||||
|
||||
long long m_mark;
|
||||
|
||||
uint m_rowsLg2;
|
||||
uint m_rows;
|
||||
|
||||
uint m_waysLg2;
|
||||
uint m_ways;
|
||||
|
||||
uint m_entryCount;
|
||||
|
||||
CGLMPairCacheEntry *m_entries; // array[ m_rows ][ m_ways ]
|
||||
|
||||
uint *m_evictions; // array[ m_rows ];
|
||||
uint *m_hits; // array[ m_rows ];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
436
external/steamworks/glmgr/cglmquery.cpp
vendored
Normal file
436
external/steamworks/glmgr/cglmquery.cpp
vendored
Normal file
@@ -0,0 +1,436 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// cglmquery.cpp
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#include "glmgr.h"
|
||||
#include "cglmquery.h"
|
||||
#include "dxabstract.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
//===============================================================================
|
||||
|
||||
extern int gl_errorcheckall;
|
||||
extern int gl_errorcheckqueries;
|
||||
extern int 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" );
|
||||
int gl_nullqueries = 0;
|
||||
|
||||
GLenum GetQueryError( void )
|
||||
{
|
||||
if ( ( GLMDEBUG || (gl_errorcheckall != 0) || (gl_errorcheckqueries != 0) ) && (gl_errorchecknone == 0) )
|
||||
{
|
||||
return glGetError();
|
||||
}
|
||||
else
|
||||
{
|
||||
return (GLenum) 0; // whistle past graveyard
|
||||
}
|
||||
}
|
||||
|
||||
//===============================================================================
|
||||
|
||||
CGLMQuery::CGLMQuery( GLMContext *ctx, GLMQueryParams *params )
|
||||
{
|
||||
// make sure context is current
|
||||
// get the type of query requested
|
||||
// generate name(s) needed
|
||||
// set initial state appropriately
|
||||
ctx->MakeCurrent();
|
||||
|
||||
m_ctx = ctx;
|
||||
m_params = *params;
|
||||
|
||||
m_name = 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)
|
||||
glGenQueriesARB( 1, &m_name );
|
||||
GLMPRINTF(("-A- CGLMQuery(OQ) created name %d", m_name));
|
||||
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::CGLMQuery (OQ) saw %s error (%d) from glGenQueriesARB", decodedStr, errorcode );
|
||||
m_name = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
{
|
||||
//make a fence - no aux fence needed
|
||||
glGenFencesAPPLE(1, &m_name );
|
||||
GLMPRINTF(("-A- CGLMQuery(fence) created name %d", m_name));
|
||||
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::CGLMQuery (fence) saw %s error (%d) from glGenFencesAPPLE", decodedStr, errorcode );
|
||||
m_name = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CGLMQuery::~CGLMQuery()
|
||||
{
|
||||
GLMPRINTF(("-A-> ~CGLMQuery"));
|
||||
|
||||
// make sure query has completed (might not be necessary)
|
||||
// delete the name(s)
|
||||
|
||||
m_ctx->MakeCurrent();
|
||||
|
||||
switch(m_params.m_type)
|
||||
{
|
||||
case EOcclusion:
|
||||
{
|
||||
// do a finish occlusion query ?
|
||||
GLMPRINTF(("-A- ~CGLMQuery(OQ) deleting name %d", m_name));
|
||||
glDeleteQueries(1, &m_name );
|
||||
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::~CGLMQuery (OQ) saw %s error (%d) from glDeleteQueries", decodedStr, errorcode );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
{
|
||||
// do a finish fence ?
|
||||
GLMPRINTF(("-A- ~CGLMQuery(fence) deleting name %d", m_name));
|
||||
glDeleteFencesAPPLE(1, &m_name );
|
||||
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::~CGLMQuery (fence) saw %s error (%d) from glDeleteFencesAPPLE", decodedStr, errorcode );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_name = 0;
|
||||
|
||||
GLMPRINTF(("-A-< ~CGLMQuery"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void CGLMQuery::Start( void ) // "start counting"
|
||||
{
|
||||
m_ctx->MakeCurrent();
|
||||
|
||||
// on occlusion query:
|
||||
// glBeginQueryARB on the OQ name. counting starts.
|
||||
|
||||
// on fence: glSetFence on m_name.
|
||||
|
||||
// note, fences finish themselves via command progress - OQ's do not.
|
||||
|
||||
Assert(!m_started);
|
||||
Assert(!m_stopped);
|
||||
Assert(!m_done);
|
||||
|
||||
m_nullQuery = (gl_nullqueries != 0); // latch value for remainder of query life
|
||||
|
||||
switch(m_params.m_type)
|
||||
{
|
||||
case EOcclusion:
|
||||
{
|
||||
if (m_nullQuery)
|
||||
{
|
||||
// do nothing..
|
||||
}
|
||||
else
|
||||
{
|
||||
glBeginQueryARB( GL_SAMPLES_PASSED_ARB, m_name );
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::Start(OQ) saw %s error (%d) from glBeginQueryARB (GL_SAMPLES_PASSED_ARB) name=%d", decodedStr, errorcode, m_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
{
|
||||
glSetFenceAPPLE( m_name );
|
||||
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::Start(fence) saw %s error (%d) from glSetFenceAPPLE name=%d", decodedStr, errorcode, m_name );
|
||||
}
|
||||
|
||||
m_stopped = true; // caller should not call Stop on a fence, it self-stops
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_started = true;
|
||||
}
|
||||
|
||||
void CGLMQuery::Stop( void ) // "stop counting"
|
||||
{
|
||||
m_ctx->MakeCurrent();
|
||||
|
||||
Assert(m_started);
|
||||
Assert(!m_stopped); // this will assert if you try to call Stop on a fence that is started
|
||||
Assert(!m_done);
|
||||
|
||||
switch(m_params.m_type)
|
||||
{
|
||||
case EOcclusion:
|
||||
{
|
||||
if (m_nullQuery)
|
||||
{
|
||||
// do nothing..
|
||||
}
|
||||
else
|
||||
{
|
||||
glEndQueryARB( GL_SAMPLES_PASSED_ARB ); // we are only putting the request-to-stop-counting into the cmd stream.
|
||||
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::Stop(OQ) saw %s error (%d) from glEndQueryARB( GL_SAMPLES_PASSED_ARB ) name=%d", decodedStr, errorcode, m_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
{
|
||||
// nop - you don't "end" a fence, you just test it and/or finish it out in Complete
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_stopped = true;
|
||||
}
|
||||
|
||||
bool CGLMQuery::IsDone( void )
|
||||
{
|
||||
m_ctx->MakeCurrent();
|
||||
|
||||
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: glTestFenceAPPLE 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;
|
||||
glGetQueryObjectivARB(m_name, GL_QUERY_RESULT_AVAILABLE_ARB, &available );
|
||||
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::IsDone saw %s error (%d) from glGetQueryObjectivARB(a2) name=%d", decodedStr, errorcode, m_name );
|
||||
}
|
||||
|
||||
m_done = (available != 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
{
|
||||
m_done = glTestFenceAPPLE( m_name );
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::IsDone saw %s error (%d) from glTestFenceAPPLE(b) name=%d", decodedStr, errorcode, m_name );
|
||||
}
|
||||
|
||||
if (m_done)
|
||||
{
|
||||
glFinishFenceAPPLE( m_name ); // no set fence goes un-finished
|
||||
|
||||
errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::IsDone saw %s error (%d) from glFinishFenceAPPLE(b) name=%d", decodedStr, errorcode, m_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return m_done;
|
||||
}
|
||||
|
||||
void CGLMQuery::Complete( uint *result )
|
||||
{
|
||||
m_ctx->MakeCurrent();
|
||||
|
||||
uint resultval = 0;
|
||||
GLint available = 0;
|
||||
|
||||
// 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
|
||||
{
|
||||
// accept that the query is going to drain pipe in 10.6.4 and prior.
|
||||
// check the error on the spot.
|
||||
glGetQueryObjectivARB(m_name, GL_QUERY_RESULT_AVAILABLE_ARB, &available );
|
||||
GLenum errorcode = GetQueryError();
|
||||
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::Complete saw %s error (%d) from glGetQueryObjectivARB GL_QUERY_RESULT_AVAILABLE_ARB name=%d", decodedStr, errorcode, m_name );
|
||||
|
||||
resultval=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!available)
|
||||
{
|
||||
// this does happen with some very modest frequency.
|
||||
if (!m_ctx->Caps().m_hasPerfPackage1)
|
||||
{
|
||||
glFlush(); // ISTR some deadlock cases on pre-SLGU drivers if you didn't do this to kick the queue along..
|
||||
}
|
||||
}
|
||||
|
||||
glGetQueryObjectuivARB( m_name, GL_QUERY_RESULT_ARB, &resultval);
|
||||
|
||||
errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::Complete saw %s error (%d) from glGetQueryObjectivARB GL_QUERY_RESULT_ARB name=%d", decodedStr, errorcode, m_name );
|
||||
|
||||
resultval=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// resultval is legit
|
||||
}
|
||||
}
|
||||
m_done = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EFence:
|
||||
{
|
||||
if(!m_done)
|
||||
{
|
||||
glFinishFenceAPPLE( m_name );
|
||||
|
||||
GLenum errorcode = GetQueryError();
|
||||
if (errorcode)
|
||||
{
|
||||
const char *decodedStr = GLMDecode( eGL_ERROR, errorcode );
|
||||
printf( "\nCGLMQuery::Complete saw %s error (%d) from glFinishFenceAPPLE (EFence) name=%d", decodedStr, errorcode, m_name );
|
||||
}
|
||||
|
||||
m_done = true; // for clarity or if they try to Complete twice
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
84
external/steamworks/glmgr/cglmquery.h
vendored
Normal file
84
external/steamworks/glmgr/cglmquery.h
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// cglmquery.h
|
||||
// GLMgr queries
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef CGLMQUERY_H
|
||||
#define CGLMQUERY_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef OSX
|
||||
#include "glmgrbasics.h"
|
||||
#endif
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// forward declarations
|
||||
|
||||
class GLMContext;
|
||||
class CGLMQuery;
|
||||
|
||||
//===============================================================================
|
||||
|
||||
enum EGLMQueryType
|
||||
{
|
||||
EOcclusion,
|
||||
EFence,
|
||||
EGLMQueryCount
|
||||
};
|
||||
|
||||
struct GLMQueryParams
|
||||
{
|
||||
EGLMQueryType m_type;
|
||||
};
|
||||
|
||||
class CGLMQuery
|
||||
{
|
||||
// leave everything public til it's running
|
||||
public:
|
||||
friend class GLMContext; // only GLMContext can make CGLMTex objects
|
||||
friend 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
|
||||
|
||||
bool m_started;
|
||||
bool m_stopped;
|
||||
bool m_done;
|
||||
|
||||
bool m_nullQuery; // was gl_nullqueries true at Start time - if so, continue to act like a null query through Stop/IsDone/Complete time
|
||||
// restated - only Start should examine the convar.
|
||||
|
||||
CGLMQuery( GLMContext *ctx, GLMQueryParams *params );
|
||||
~CGLMQuery( );
|
||||
|
||||
// for an occlusion query:
|
||||
// Start = BeginQuery query-start goes into stream
|
||||
// Stop = EndQuery query-end goes into stream - a fence is also set so we can probe for completion
|
||||
// IsDone = TestFence use the added fence to ask if query-end has passed (i.e. will Complete block?)
|
||||
// Complete = GetQueryObjectuivARB(uint id, enum pname, uint *params) - extract the sample count
|
||||
|
||||
// for a fence query:
|
||||
// Start = SetFence fence goes into command stream
|
||||
// Stop = NOP fences are self finishing - no need to call Stop on a fence
|
||||
// IsDone = TestFence ask if fence passed
|
||||
// Complete = FinishFence
|
||||
|
||||
void Start ( void );
|
||||
void Stop ( void );
|
||||
bool IsDone ( void );
|
||||
void Complete ( uint *result );
|
||||
|
||||
// accessors for the started/stopped state
|
||||
bool IsStarted ( void );
|
||||
bool IsStopped ( void );
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
1816
external/steamworks/glmgr/cglmtex.cpp
vendored
Normal file
1816
external/steamworks/glmgr/cglmtex.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
291
external/steamworks/glmgr/cglmtex.h
vendored
Normal file
291
external/steamworks/glmgr/cglmtex.h
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// cglmtex.h
|
||||
// GLMgr textures
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef CGLMTEX_H
|
||||
#define CGLMTEX_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef OSX
|
||||
#include "glmgrbasics.h"
|
||||
#endif
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// forward declarations
|
||||
|
||||
class GLMContext;
|
||||
class GLMTester;
|
||||
class CGLMTexLayoutTable;
|
||||
class CGLMTex;
|
||||
class CGLMFBO;
|
||||
|
||||
struct IDirect3DSurface9;
|
||||
|
||||
//===============================================================================
|
||||
|
||||
struct GLMTexFormatDesc
|
||||
{
|
||||
const char *m_formatSummary; // for debug visibility
|
||||
|
||||
D3DFORMAT m_d3dFormat; // what D3D knows it as; see public/bitmap/imageformat.h
|
||||
|
||||
GLenum m_glIntFormat; // GL internal format
|
||||
GLenum m_glIntFormatSRGB; // internal format if SRGB flavor
|
||||
GLenum m_glDataFormat; // GL data format
|
||||
GLenum m_glDataType; // GL data type
|
||||
|
||||
int m_chunkSize; // 1 or 4 - 4 is used for compressed textures
|
||||
int m_bytesPerSquareChunk; // how many bytes for the smallest quantum (m_chunkSize x m_chunkSize)
|
||||
// this description lets us calculate size cleanly without conditional logic for compression
|
||||
};
|
||||
const GLMTexFormatDesc *GetFormatDesc( D3DFORMAT format );
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// utility function for generating slabs of texels. mostly for test.
|
||||
typedef struct
|
||||
{
|
||||
// in
|
||||
D3DFORMAT m_format;
|
||||
void *m_dest; // dest address
|
||||
int m_chunkCount; // square chunk count (single texels or compressed blocks)
|
||||
int m_byteCountLimit; // caller expectation of max number of bytes to write out
|
||||
float r,g,b,a; // color desired
|
||||
|
||||
// out
|
||||
int m_bytesWritten;
|
||||
} GLMGenTexelParams;
|
||||
|
||||
// return true if successful
|
||||
bool GLMGenTexels( GLMGenTexelParams *params );
|
||||
|
||||
|
||||
//===============================================================================
|
||||
|
||||
struct GLMTexLayoutSlice
|
||||
{
|
||||
int m_xSize,m_ySize,m_zSize; //texel dimensions of this slice
|
||||
int m_storageOffset; //where in the storage slab does this slice live
|
||||
int m_storageSize; //how much storage does this slice occupy
|
||||
};
|
||||
|
||||
enum EGLMTexFlags
|
||||
{
|
||||
kGLMTexMipped = 0x01,
|
||||
kGLMTexMippedAuto = 0x02,
|
||||
kGLMTexRenderable = 0x04,
|
||||
kGLMTexIsStencil = 0x08,
|
||||
kGLMTexIsDepth = 0x10,
|
||||
kGLMTexSRGB = 0x20,
|
||||
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
|
||||
};
|
||||
|
||||
struct LessThan_GLMTexLayoutKey
|
||||
{
|
||||
bool operator()(const GLMTexLayoutKey &a, const GLMTexLayoutKey &b) const
|
||||
{
|
||||
#define DO_LESS(fff) if (a.fff != b.fff) { return (a.fff< b.fff); }
|
||||
|
||||
DO_LESS(m_texGLTarget);
|
||||
DO_LESS(m_texFormat);
|
||||
DO_LESS(m_texFlags);
|
||||
DO_LESS(m_xSize);
|
||||
DO_LESS(m_ySize)
|
||||
DO_LESS(m_zSize);
|
||||
|
||||
#undef DO_LESS
|
||||
|
||||
return false; // they are equal
|
||||
}
|
||||
};
|
||||
|
||||
#define GLM_TEX_MAX_MIPS 14
|
||||
#define GLM_TEX_MAX_FACES 6
|
||||
#define GLM_TEX_MAX_SLICES (GLM_TEX_MAX_MIPS * GLM_TEX_MAX_FACES)
|
||||
|
||||
struct GLMTexLayout
|
||||
{
|
||||
char *m_layoutSummary; // for debug visibility
|
||||
|
||||
// const inputs used for hashing
|
||||
GLMTexLayoutKey m_key;
|
||||
|
||||
// refcount
|
||||
int m_refCount;
|
||||
|
||||
// derived values:
|
||||
GLMTexFormatDesc *m_format; // format specific info
|
||||
int m_mipCount; // derived by starying at base size and working down towards 1x1
|
||||
int m_faceCount; // 1 for 2d/3d, 6 for cubemap
|
||||
int m_sliceCount; // product of faces and mips
|
||||
int m_storageTotalSize; // size of storage slab required
|
||||
|
||||
// slice array
|
||||
GLMTexLayoutSlice m_slices[0]; // dynamically allocated 2-d array [faces][mips]
|
||||
};
|
||||
|
||||
typedef std::map< GLMTexLayoutKey, GLMTexLayout*, LessThan_GLMTexLayoutKey > GLMTexLayoutKeyMap;
|
||||
class CGLMTexLayoutTable
|
||||
{
|
||||
public:
|
||||
CGLMTexLayoutTable();
|
||||
|
||||
GLMTexLayout *NewLayoutRef( GLMTexLayoutKey *key ); // pass in a pointer to layout key - receive ptr to completed layout
|
||||
void DelLayoutRef( GLMTexLayout *layout ); // pass in pointer to completed layout. refcount is dropped.
|
||||
|
||||
void DumpStats( void );
|
||||
protected:
|
||||
GLMTexLayoutKeyMap m_layoutMap;
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// a sampler specifies desired state for drawing on a given sampler index
|
||||
// this is the combination of a texture choice and a set of sampler parameters
|
||||
// see http://msdn.microsoft.com/en-us/library/bb172602(VS.85).aspx
|
||||
|
||||
|
||||
struct GLMTexSamplingParams
|
||||
{
|
||||
GLenum m_addressModes[3]; // S, T, R
|
||||
GLfloat m_borderColor[4]; // R,G,B,A
|
||||
|
||||
GLenum m_magFilter;
|
||||
GLenum m_minFilter;
|
||||
|
||||
GLfloat m_mipmapBias;
|
||||
GLint m_minMipLevel;
|
||||
GLint m_maxMipLevel;
|
||||
GLint m_maxAniso;
|
||||
GLenum m_compareMode; // only used for depth and stencil type textures
|
||||
bool m_srgb; // srgb texture read...
|
||||
};
|
||||
|
||||
struct GLMTexLockParams
|
||||
{
|
||||
// input params which identify the slice of interest
|
||||
CGLMTex *m_tex;
|
||||
int m_face;
|
||||
int m_mip;
|
||||
|
||||
// identifies the region of the slice
|
||||
GLMRegion m_region;
|
||||
|
||||
// tells GLM to force re-read of the texels back from GL
|
||||
// i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale"
|
||||
bool m_readback;
|
||||
};
|
||||
|
||||
struct GLMTexLockDesc
|
||||
{
|
||||
GLMTexLockParams m_req; // form of the lock request
|
||||
|
||||
bool m_active; // set true at lock time. cleared at unlock time.
|
||||
|
||||
int m_sliceIndex; // which slice in the layout
|
||||
int m_sliceBaseOffset; // where is that in the texture data
|
||||
int m_sliceRegionOffset; // offset to the start (lowest address corner) of the region requested
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
#define GLM_SAMPLER_COUNT 16
|
||||
|
||||
typedef unsigned short CTexBindMask; // 16 bits, who needs bitvec...
|
||||
|
||||
enum EGLMTexSliceFlag
|
||||
{
|
||||
kSliceValid = 0x01, // slice has been teximage'd in whole at least once - set to 0 initially
|
||||
kSliceStorageValid = 0x02, // if backing store is available, this slice's data is a valid copy - set to 0 initially
|
||||
kSliceLocked = 0x04, // are one or more locks outstanding on this slice
|
||||
kSliceFullyDirty = 0x08, // does the slice need to be fully downloaded at unlock time (disregard dirty rects)
|
||||
};
|
||||
|
||||
class CGLMTex
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
void Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut, int *zStrideOut );
|
||||
void Unlock( GLMTexLockParams *params );
|
||||
|
||||
protected:
|
||||
friend class GLMContext; // only GLMContext can make CGLMTex objects
|
||||
friend class GLMTester;
|
||||
friend class CGLMFBO;
|
||||
|
||||
friend struct IDirect3DDevice9;
|
||||
friend struct IDirect3DBaseTexture9;
|
||||
friend struct IDirect3DTexture9;
|
||||
friend struct IDirect3DSurface9;
|
||||
friend struct IDirect3DCubeTexture9;
|
||||
friend struct IDirect3DVolumeTexture9;
|
||||
|
||||
CGLMTex( GLMContext *ctx, GLMTexLayout *layout, GLMTexSamplingParams *sampling, const char *debugLabel = NULL );
|
||||
~CGLMTex( );
|
||||
|
||||
int CalcSliceIndex( int face, int mip );
|
||||
void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut );
|
||||
|
||||
void ApplySamplingParams( GLMTexSamplingParams *params, bool noCheck=FALSE );
|
||||
|
||||
void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true );
|
||||
void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false );
|
||||
// last param lets us send NULL data ptr (only legal with uncompressed formats, beware)
|
||||
// this helps out ResetSRGB.
|
||||
|
||||
void ResetSRGB( bool srgb, bool noDataWrite );
|
||||
// re-specify texture format to match desired sRGB form
|
||||
// noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's
|
||||
|
||||
GLMTexLayout *m_layout; // layout of texture (shared across all tex with same layout)
|
||||
int m_minActiveMip;//index of lowest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL.
|
||||
int m_maxActiveMip;//index of highest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL.
|
||||
|
||||
GLMTexSamplingParams m_sampling; // mirror of sampling params currently embodied in the texture
|
||||
// (consult this at draw time, in order to know if changes need to be made)
|
||||
|
||||
GLMContext *m_ctx; // link back to parent context
|
||||
|
||||
GLuint m_texName; // name of this texture in the context
|
||||
bool m_texClientStorage; // was CS selecetd for texture
|
||||
bool m_texPreloaded; // has it been kicked into VRAM with GLMContext::PreloadTex yet
|
||||
|
||||
GLuint m_rboName; // name of MSAA RBO backing the tex if MSAA enabled (or zero)
|
||||
bool m_rboDirty; // has RBO been drawn on - i.e. needs to be blitted back to texture if texture is going to be sampled from
|
||||
|
||||
CTexBindMask m_bindPoints; // true for each place in the parent ctx where currently
|
||||
// bound (indexed via EGLMTexCtxBindingIndex)
|
||||
|
||||
int m_rtAttachCount; // how many RT's have this texture attached somewhere
|
||||
|
||||
char *m_backing; // backing storage if available
|
||||
|
||||
int m_lockCount; // lock reqs are stored in the GLMContext for tracking
|
||||
|
||||
std::vector<unsigned char> m_sliceFlags;
|
||||
|
||||
char *m_debugLabel; // strdup() of debugLabel passed in, or NULL
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
3524
external/steamworks/glmgr/dx9asmtogl2.cpp
vendored
Normal file
3524
external/steamworks/glmgr/dx9asmtogl2.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
233
external/steamworks/glmgr/dx9asmtogl2.h
vendored
Normal file
233
external/steamworks/glmgr/dx9asmtogl2.h
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// DX9AsmToGL2.h
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef DX9_ASM_TO_GL_2_H
|
||||
#define DX9_ASM_TO_GL_2_H
|
||||
|
||||
#include "glmgr.h"
|
||||
|
||||
//==============================================================================
|
||||
|
||||
|
||||
#define DISASM_OK 0
|
||||
#define DISASM_ERROR 1
|
||||
|
||||
#define MAX_SHADER_CONSTANTS 512
|
||||
|
||||
#define MAX_DECLARED_OUTPUTS 32
|
||||
|
||||
#define HEXCODE_HEADER "// Hex: "
|
||||
|
||||
// Option bits
|
||||
#define D3DToGL_OptionUseEnvParams 0x001
|
||||
#define D3DToGL_OptionDoFixupZ 0x002 // Add instructions to put Z in the right interval for GL
|
||||
#define D3DToGL_OptionDoFixupY 0x004 // Add instructions to flip the Y over for GL
|
||||
#define D3DToGL_OptionDoUserClipPlanes 0x008 // 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_OptionGLSL 0x010 // Output GLSL, rather than ASM
|
||||
#define D3DToGL_AddHexComments 0x020 // Include hex comments in the code for debugging
|
||||
#define D3DToGL_PutHexCommentsAfterLines 0x040 // If D3DToGL_AddHexComments is set, this puts the codes to the right, rather than on separate lines
|
||||
#define D3DToGL_GeneratingDebugText 0x080 // This tells it that we're just getting info for debugging so go easy on asserts and errors
|
||||
#define D3DToGL_OptionAllowStaticControlFlow 0x100
|
||||
#define D3DToGL_OptionUseBindableUniforms 0x200 // add "bindable" in front of "vc" / "pc" constant arrays (GLSL only)
|
||||
#define D3DToGL_OptionSRGBWriteSuffix 0x400 // Tack sRGB conversion suffix on to pixel shaders
|
||||
#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_bUseBindableUniforms; // set D3DToGL_OptionUseBindableUniforms
|
||||
bool m_bGenerateSRGBWriteSuffix; // set D3DToGL_OptionSRGBWriteSuffix
|
||||
|
||||
// Default: false
|
||||
// If you set this to true, it'll convert to GLSL instead of GL ASM.
|
||||
bool m_bGLSL; // set D3DToGL_OptionGLSL
|
||||
|
||||
// Default: false
|
||||
bool m_bAllowStaticControlFlow; // set D3DToGL_OptionAllowStaticControlFlow
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
bool m_bOutputColorRegister[4];
|
||||
bool m_bOutputDepthRegister;
|
||||
|
||||
// Declaration of integer and bool constants
|
||||
uint32 m_dwConstIntUsageMask;
|
||||
uint32 m_dwConstBoolUsageMask;
|
||||
|
||||
// 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_nShadowDepthSampler;
|
||||
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;
|
||||
|
||||
// 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];
|
||||
|
||||
// Have they used the tangent input semantic (i.e. is g_pTangentAttributeName declared)?
|
||||
bool m_bTangentInputUsed;
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
// 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 NoteTangentInputUsed();
|
||||
|
||||
void Handle_DCL();
|
||||
void Handle_DEF();
|
||||
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 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 nShadowDepthSampler, uint32 nCentroidMask, char *debugLabel );
|
||||
};
|
||||
|
||||
|
||||
#endif // DX9_ASM_TO_GL_2_H
|
||||
5951
external/steamworks/glmgr/dxabstract.cpp
vendored
Normal file
5951
external/steamworks/glmgr/dxabstract.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2420
external/steamworks/glmgr/dxabstract.h
vendored
Normal file
2420
external/steamworks/glmgr/dxabstract.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
45
external/steamworks/glmgr/glmdebug.h
vendored
Normal file
45
external/steamworks/glmgr/glmdebug.h
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef GLMDEBUG_H
|
||||
#define GLMDEBUG_H
|
||||
|
||||
// include this anywhere you need to be able to compile-out code related specifically to GLM debugging.
|
||||
|
||||
// we expect DEBUG to be driven by the build system so you can include this header anywhere.
|
||||
// when we come out, GLMDEBUG will be defined to a value - 0, 1, or 2
|
||||
// 0 means no GLM debugging is possible
|
||||
// 1 means it's possible and resulted from being a debug build
|
||||
// 2 means it's possible and resulted from being manually forced on for a release build
|
||||
|
||||
#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
|
||||
|
||||
// helpful macro if you are in a position to call GLM functions directly (i.e. you live in materialsystem / shaderapidx9)
|
||||
#if GLMDEBUG
|
||||
#define GLMPRINTF(args) GLMPrintf args
|
||||
#define GLMPRINTSTR(args) GLMPrintStr args
|
||||
#define GLMPRINTTEXT(args) GLMPrintText args
|
||||
#define GLMBEGINPIXEVENT(args) GLMBeginPIXEvent args
|
||||
#define GLMENDPIXEVENT(args) GLMEndPIXEvent args
|
||||
#else
|
||||
#define GLMPRINTF(args)
|
||||
#define GLMPRINTSTR(args)
|
||||
#define GLMPRINTTEXT(args)
|
||||
#define GLMBEGINPIXEVENT(args)
|
||||
#define GLMENDPIXEVENT(args)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
275
external/steamworks/glmgr/glmdisplay.h
vendored
Normal file
275
external/steamworks/glmgr/glmdisplay.h
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// glmdisplay.h
|
||||
// display related stuff - used by both GLMgr and the CocoaMgr
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef GLMDISPLAY_H
|
||||
#define GLMDISPLAY_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/CGLRenderers.h>
|
||||
#include <OpenGL/CGLCurrent.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
#include "glmgrbasics.h"
|
||||
|
||||
typedef void _PseudoNSGLContext; // aka NSOpenGLContext
|
||||
typedef _PseudoNSGLContext *PseudoNSGLContextPtr;
|
||||
|
||||
struct GLMDisplayModeInfoFields
|
||||
{
|
||||
uint m_modePixelWidth;
|
||||
uint m_modePixelHeight;
|
||||
uint m_modeRefreshHz;
|
||||
// are we even going to talk about bit depth... not yet
|
||||
};
|
||||
|
||||
struct GLMDisplayInfoFields
|
||||
{
|
||||
CGDirectDisplayID m_cgDisplayID;
|
||||
CGOpenGLDisplayMask m_glDisplayMask; // result of CGDisplayIDToOpenGLDisplayMask on the cg_displayID.
|
||||
|
||||
uint m_displayPixelWidth;
|
||||
uint m_displayPixelHeight;
|
||||
};
|
||||
|
||||
struct GLMRendererInfoFields
|
||||
{
|
||||
/*properties of interest and their desired values.
|
||||
|
||||
kCGLRPFullScreen = 54, true
|
||||
kCGLRPAccelerated = 73, true
|
||||
kCGLRPWindow = 80, true
|
||||
|
||||
kCGLRPRendererID = 70, informational
|
||||
kCGLRPDisplayMask = 84, informational
|
||||
kCGLRPBufferModes = 100, informational
|
||||
kCGLRPColorModes = 103, informational
|
||||
kCGLRPAccumModes = 104, informational
|
||||
kCGLRPDepthModes = 105, informational
|
||||
kCGLRPStencilModes = 106, informational
|
||||
kCGLRPMaxAuxBuffers = 107, informational
|
||||
kCGLRPMaxSampleBuffers = 108, informational
|
||||
kCGLRPMaxSamples = 109, informational
|
||||
kCGLRPSampleModes = 110, informational
|
||||
kCGLRPSampleAlpha = 111, informational
|
||||
kCGLRPVideoMemory = 120, informational
|
||||
kCGLRPTextureMemory = 121, informational
|
||||
kCGLRPRendererCount = 128 number of renderers in the CGLRendererInfoObj under examination
|
||||
|
||||
kCGLRPOffScreen = 53, D/C
|
||||
kCGLRPRobust = 75, FALSE or D/C - aka we're asking for no-fallback
|
||||
kCGLRPBackingStore = 76, D/C
|
||||
kCGLRPMPSafe = 78, D/C
|
||||
kCGLRPMultiScreen = 81, D/C
|
||||
kCGLRPCompliant = 83, D/C
|
||||
*/
|
||||
|
||||
|
||||
//--------------------------- info we have from CGL renderer queries, IOKit, Gestalt
|
||||
//--------------------------- these are set up in the displayDB by CocoaMgr
|
||||
GLint m_fullscreen;
|
||||
GLint m_accelerated;
|
||||
GLint m_windowed;
|
||||
|
||||
GLint m_rendererID;
|
||||
GLint m_displayMask;
|
||||
GLint m_bufferModes;
|
||||
GLint m_colorModes;
|
||||
GLint m_accumModes;
|
||||
GLint m_depthModes;
|
||||
GLint m_stencilModes;
|
||||
|
||||
GLint m_maxAuxBuffers;
|
||||
GLint m_maxSampleBuffers;
|
||||
GLint m_maxSamples;
|
||||
GLint m_sampleModes;
|
||||
GLint m_sampleAlpha;
|
||||
|
||||
GLint m_vidMemory;
|
||||
GLint m_texMemory;
|
||||
|
||||
uint m_pciVendorID;
|
||||
uint m_pciDeviceID;
|
||||
char m_pciModelString[64];
|
||||
char m_driverInfoString[64];
|
||||
|
||||
//--------------------------- OS version related - set up by CocoaMgr
|
||||
|
||||
// OS version found
|
||||
uint m_osComboVersion; // 0x00XXYYZZ : XX major, YY minor, ZZ minor minor : 10.6.3 --> 0x000A0603. 10.5.8 --> 0x000A0508.
|
||||
|
||||
//--------------------------- shorthands - also set up by CocoaMgr - driven by vendorid / deviceid
|
||||
|
||||
bool m_ati;
|
||||
bool m_atiR5xx;
|
||||
bool m_atiR6xx;
|
||||
bool m_atiR7xx;
|
||||
bool m_atiR8xx;
|
||||
bool m_atiNewer;
|
||||
|
||||
bool m_intel;
|
||||
bool m_intel95x;
|
||||
bool m_intel3100;
|
||||
bool m_intelNewer;
|
||||
|
||||
bool m_nv;
|
||||
bool m_nvG7x;
|
||||
bool m_nvG8x;
|
||||
bool m_nvNewer;
|
||||
|
||||
//--------------------------- context query results - left blank in the display DB - but valid in a GLMContext (call ctx->Caps() to get a const ref)
|
||||
|
||||
// booleans
|
||||
bool m_hasGammaWrites; // aka glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT) / glEnable(GL_FRAMEBUFFER_SRGB_EXT)
|
||||
bool m_hasMixedAttachmentSizes; // aka ARB_fbo in 10.6.3 - test for min OS vers, then exported ext string
|
||||
bool m_hasBGRA; // aka GL_BGRA vertex attribs in 10.6.3 - - test for min OS vers, then exported ext string
|
||||
bool m_hasNewFullscreenMode; // aka 10.6.x "big window" fullscreen mode
|
||||
bool m_hasNativeClipVertexMode; // aka GLSL gl_ClipVertex does not fall back to SW- OS version and folklore-based
|
||||
bool m_hasOcclusionQuery; // occlusion query: do you speak it ?!
|
||||
bool m_hasFramebufferBlit; // framebuffer blit: know what I'm sayin?!
|
||||
bool m_hasPerfPackage1; // means new MTGL, fast OQ, fast uniform upload, NV can resolve flipped (late summer 2010 post 10.6.4 update)
|
||||
|
||||
// counts
|
||||
int m_maxAniso; // aniso limit - context query
|
||||
|
||||
// other exts
|
||||
bool m_hasBindableUniforms;
|
||||
bool m_hasUniformBuffers;
|
||||
|
||||
// runtime options that aren't negotiable once set
|
||||
bool m_hasDualShaders; // must supply CLI arg "-glmdualshaders" or we go GLSL only
|
||||
|
||||
//--------------------------- " can'ts " - specific problems that need to be worked around
|
||||
|
||||
bool m_cantBlitReliably; // Intel chipsets have problems blitting sRGB sometimes
|
||||
bool m_cantAttachSRGB; // NV G8x on 10.5.8 can't have srgb tex on FBO color - separate issue from hasGammaWrites
|
||||
bool m_cantResolveFlipped; // happens on NV in 10.6.4 and prior - console variable "gl_can_resolve_flipped" can overrule
|
||||
bool m_cantResolveScaled; // happens everywhere per GL spec but may be relaxed some day - console variable "gl_can_resolve_scaled" can overrule
|
||||
bool m_costlyGammaFlips; // this means that sRGB sampling state affects shader code gen, resulting in state-dependent code regen
|
||||
|
||||
|
||||
//--------------------------- " bads " - known bad drivers
|
||||
bool m_badDriver1064NV; // this is the bad NVIDIA driver on 10.6.4 - stutter, tex corruption, black screen issues
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// this stuff is all sitting in glmgrcocoa.mm since it needs to make ObjC calls.
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// modes, displays, and renderers
|
||||
// think of renderers as being at the top of a tree.
|
||||
// each renderer has displays hanging off of it.
|
||||
// each display has modes hanging off of it.
|
||||
// the tree is populated on demand and then queried as needed.
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// GLMDisplayModeInfoFields is in glmdisplay.h
|
||||
|
||||
class GLMDisplayMode
|
||||
{
|
||||
public:
|
||||
GLMDisplayModeInfoFields m_info;
|
||||
|
||||
GLMDisplayMode( uint width, uint height, uint refreshHz );
|
||||
~GLMDisplayMode( void );
|
||||
|
||||
void Dump( int which );
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// GLMDisplayInfoFields is in glmdisplay.h
|
||||
|
||||
class GLMDisplayInfo
|
||||
{
|
||||
public:
|
||||
GLMDisplayInfoFields m_info;
|
||||
std::vector< GLMDisplayMode* > *m_modes; // starts out NULL, set by PopulateModes
|
||||
|
||||
GLMDisplayInfo( CGDirectDisplayID displayID, CGOpenGLDisplayMask displayMask );
|
||||
~GLMDisplayInfo( void );
|
||||
|
||||
void PopulateModes( void );
|
||||
|
||||
void Dump( int which );
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// GLMRendererInfoFields is in glmdisplay.h
|
||||
|
||||
class GLMRendererInfo
|
||||
{
|
||||
public:
|
||||
GLMRendererInfoFields m_info;
|
||||
std::vector< GLMDisplayInfo* > *m_displays; // starts out NULL, set by PopulateDisplays
|
||||
|
||||
GLMRendererInfo ( GLMRendererInfoFields *info );
|
||||
~GLMRendererInfo ( void );
|
||||
|
||||
void PopulateDisplays( void );
|
||||
void Dump( int which );
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
class GLMDisplayDB
|
||||
{
|
||||
public:
|
||||
std::vector< GLMRendererInfo* > *m_renderers; // starts out NULL, set by PopulateRenderers
|
||||
|
||||
std::vector< GLMFakeAdapter > m_fakeAdapters;
|
||||
|
||||
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
|
||||
7113
external/steamworks/glmgr/glmgr.cpp
vendored
Normal file
7113
external/steamworks/glmgr/glmgr.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1031
external/steamworks/glmgr/glmgr.h
vendored
Normal file
1031
external/steamworks/glmgr/glmgr.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4082
external/steamworks/glmgr/glmgrbasics.cpp
vendored
Normal file
4082
external/steamworks/glmgr/glmgrbasics.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
512
external/steamworks/glmgr/glmgrbasics.h
vendored
Normal file
512
external/steamworks/glmgr/glmgrbasics.h
vendored
Normal file
@@ -0,0 +1,512 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// glmgrbasics.h
|
||||
// types, common headers, forward declarations, utilities
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef GLMBASICS_H
|
||||
#define GLMBASICS_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#include <OpenGL/CGLTypes.h>
|
||||
#include <OpenGL/CGLRenderers.h>
|
||||
#include <OpenGL/CGLCurrent.h>
|
||||
//#include <OpenGL/CGLProfiler.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
#include "imageformat.h"
|
||||
#include "glmdebug.h"
|
||||
|
||||
#ifndef Assert
|
||||
#define Assert(x)
|
||||
#endif
|
||||
|
||||
//===============================================================================
|
||||
|
||||
// some portability shims to eliminate dependencies on partcular segments of Valve code
|
||||
|
||||
typedef int8_t int8;
|
||||
typedef uint8_t uint8;
|
||||
typedef int16_t int16;
|
||||
typedef uint16_t uint16;
|
||||
typedef int32_t int32;
|
||||
typedef uint32_t uint32;
|
||||
typedef int64_t int64;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
class CUtlBuffer
|
||||
{
|
||||
public:
|
||||
enum BufferFlags_t
|
||||
{
|
||||
TEXT_BUFFER = 0x1, // Describes how get + put work (as strings, or binary)
|
||||
//EXTERNAL_GROWABLE = 0x2, // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting.
|
||||
//CONTAINS_CRLF = 0x4, // For text buffers only, does this contain \n or \n\r?
|
||||
//READ_ONLY = 0x8, // For external buffers; prevents null termination from happening.
|
||||
//AUTO_TABS_DISABLED = 0x10, // Used to disable/enable push/pop tabs
|
||||
};
|
||||
|
||||
CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 )
|
||||
{
|
||||
// grow size and init flags are ignored.
|
||||
m_buf.reserve( initSize );
|
||||
};
|
||||
|
||||
CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 )
|
||||
{
|
||||
m_buf.reserve ( size );
|
||||
memcpy( &m_buf[0], pBuffer, size );
|
||||
}
|
||||
|
||||
// This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param.
|
||||
CUtlBuffer( const void *pBuffer, int size, bool crap );
|
||||
|
||||
~CUtlBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
char* Base( void )
|
||||
{
|
||||
return &m_buf[0];
|
||||
}
|
||||
|
||||
uint32 Size( void )
|
||||
{
|
||||
return m_buf.size();
|
||||
}
|
||||
|
||||
void EnsureCapacity( int num )
|
||||
{
|
||||
m_buf.resize( num );
|
||||
}
|
||||
|
||||
void AppendString( const char* pString )
|
||||
{
|
||||
int appendlen = strlen( pString ); // count of characters, null terminator not included
|
||||
if (Size())
|
||||
{
|
||||
// append to non empty string
|
||||
EnsureCapacity( Size() + appendlen + 1);
|
||||
//printf("\n **(a) appending \n---\n%s\n---\n to \n---\n%s\n---\n", pString, Base() );
|
||||
strcat( Base(), pString ); // gets NULL terminated
|
||||
}
|
||||
else
|
||||
{
|
||||
EnsureCapacity( Size() + appendlen + 1);
|
||||
//printf("\n **(b) appending \n---\n%s\n---\n to \n---\n%s\n---\n", pString, Base() );
|
||||
strcpy( Base(), pString );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
CUtlBuffer();
|
||||
|
||||
std::vector<char> m_buf;
|
||||
};
|
||||
|
||||
class CUtlString
|
||||
{
|
||||
public:
|
||||
CUtlString()
|
||||
{
|
||||
m_str = "";
|
||||
}
|
||||
|
||||
CUtlString( const char *str )
|
||||
{
|
||||
m_str = std::string( str );
|
||||
}
|
||||
|
||||
~CUtlString( )
|
||||
{
|
||||
}
|
||||
|
||||
const char* String( void )
|
||||
{
|
||||
return m_str.c_str();
|
||||
}
|
||||
|
||||
operator const char * () { return m_str.c_str(); } //conversion operator
|
||||
|
||||
private:
|
||||
|
||||
std::string m_str;
|
||||
};
|
||||
|
||||
#undef ARRAYSIZE
|
||||
#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
|
||||
|
||||
#define strcat_s(dst,lim,src) strcat(dst,src )
|
||||
|
||||
#define V_strcat(dst,lim,src) strcat(dst,src)
|
||||
#define V_vsnprintf(a,b,c,d) vsprintf(a,c,d) // double check this
|
||||
#define V_snprintf snprintf
|
||||
#define V_strncpy strncpy
|
||||
#define V_strcmp strcmp
|
||||
#define V_strlen strlen
|
||||
#define V_strstr strstr
|
||||
#define __cdecl
|
||||
|
||||
#define V_memset(dst,count,val) memset(dst,count,val)
|
||||
|
||||
int V_stricmp(const char *s1, const char *s2 );
|
||||
char const* V_stristr( char const* pStr, char const* pSearch );
|
||||
|
||||
//===============================================================================
|
||||
// types
|
||||
|
||||
// 3-d integer box (used for texture lock/unlock etc)
|
||||
struct GLMRegion
|
||||
{
|
||||
int xmin,xmax;
|
||||
int ymin,ymax;
|
||||
int zmin,zmax;
|
||||
};
|
||||
|
||||
struct GLMRect // follows GL convention - if coming from the D3D rect you will need to fiddle the Y's
|
||||
{
|
||||
int xmin; // left
|
||||
int ymin; // bottom
|
||||
int xmax; // right
|
||||
int ymax; // top
|
||||
};
|
||||
|
||||
// macros
|
||||
|
||||
//#define GLMassert(x) assert(x)
|
||||
|
||||
// forward decls
|
||||
class GLMgr; // singleton
|
||||
class GLMContext; // GL context
|
||||
class CGLMContextTester; // testing class
|
||||
class CGLMTex;
|
||||
class CGLMFBO;
|
||||
class CGLMProgram;
|
||||
class CGLMBuffer;
|
||||
|
||||
|
||||
// utilities
|
||||
|
||||
typedef enum
|
||||
{
|
||||
// D3D codes
|
||||
eD3D_DEVTYPE,
|
||||
eD3D_FORMAT,
|
||||
eD3D_RTYPE,
|
||||
eD3D_USAGE,
|
||||
eD3D_RSTATE, // render state
|
||||
eD3D_SIO, // D3D shader bytecode
|
||||
eD3D_VTXDECLUSAGE,
|
||||
|
||||
// CGL codes
|
||||
eCGL_RENDID,
|
||||
|
||||
// OpenGL error codes
|
||||
eGL_ERROR,
|
||||
|
||||
// OpenGL enums
|
||||
eGL_ENUM,
|
||||
eGL_RENDERER
|
||||
|
||||
} GLMThing_t;
|
||||
|
||||
const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const
|
||||
const char* GLMDecodeMask( GLMThing_t type, unsigned long value ); // decode a bitmask
|
||||
|
||||
void GLMStop( void ); // aka Debugger()
|
||||
void GLMCheckError( bool noStop = false, bool noLog= false );
|
||||
void GLMEnableTrace( bool on );
|
||||
|
||||
//===============================================================================
|
||||
// debug channels
|
||||
|
||||
enum EGLMDebugChannel
|
||||
{
|
||||
ePrintf,
|
||||
eDebugger,
|
||||
eGLProfiler
|
||||
};
|
||||
|
||||
#if GLMDEBUG
|
||||
// make all these prototypes disappear in non GLMDEBUG
|
||||
void GLMDebugInitialize( bool forceReinit=false );
|
||||
|
||||
bool GLMDetectOGLP( void );
|
||||
bool GLMDetectGDB( void );
|
||||
uint GLMDetectAvailableChannels( void );
|
||||
|
||||
uint GLMDebugChannelMask( uint *newValue = NULL );
|
||||
// note that GDB and OGLP can both come and go during run - forceCheck will allow that to be detected.
|
||||
// mask returned is in form of 1<<n, n from EGLMDebugChannel
|
||||
#endif
|
||||
|
||||
//===============================================================================
|
||||
// debug message flavors
|
||||
|
||||
enum EGLMDebugFlavor
|
||||
{
|
||||
eAllFlavors, // 0
|
||||
eDebugDump, // 1 debug dump flavor -D-
|
||||
eTenure, // 2 code tenures > <
|
||||
eComment, // 3 one off messages ---
|
||||
eMatrixData, // 4 matrix data -M-
|
||||
eShaderData, // 5 shader data (params) -S-
|
||||
eFrameBufData, // 6 FBO data (attachments) -F-
|
||||
eDXStuff, // 7 dxabstract spew -X-
|
||||
eAllocations, // 8 tracking allocs and frees -A-
|
||||
eSlowness, // 9 slow things happening (srgb flips..) -Z-
|
||||
eDefaultFlavor, // not specified (no marker)
|
||||
eFlavorCount
|
||||
};
|
||||
uint GLMDebugFlavorMask( uint *newValue = NULL );
|
||||
|
||||
//===============================================================================
|
||||
// output functions
|
||||
|
||||
// make all these prototypes disappear in non GLMDEBUG
|
||||
#if GLMDEBUG
|
||||
// these are unconditional outputs, they don't interrogate the string
|
||||
void GLMStringOut( const char *string );
|
||||
void GLMStringOutIndented( const char *string, int indentColumns );
|
||||
|
||||
// these will look at the string to guess its flavor: <, >, ---, -M-, -S-
|
||||
void GLMPrintfVA( const char *fmt, va_list vargs );
|
||||
void GLMPrintf( const char *fmt, ... );
|
||||
|
||||
// these take an explicit flavor with a default value
|
||||
void GLMPrintStr( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor );
|
||||
|
||||
#define GLMPRINTTEXT_NUMBEREDLINES 0x80000000
|
||||
void GLMPrintText( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor, uint options=0 ); // indent each newline
|
||||
|
||||
int GLMIncIndent( int indentDelta );
|
||||
int GLMGetIndent( void );
|
||||
void GLMSetIndent( int indent );
|
||||
|
||||
#endif
|
||||
|
||||
// expose these in release now
|
||||
// Mimic PIX events so we can decorate debug spew
|
||||
void GLMBeginPIXEvent( const char *str );
|
||||
void GLMEndPIXEvent( void );
|
||||
|
||||
//===============================================================================
|
||||
// other stuff
|
||||
|
||||
#if GLMDEBUG
|
||||
inline void GLMDebugger( void )
|
||||
{
|
||||
if (GLMDebugChannelMask() & (1<<eDebugger))
|
||||
{
|
||||
#if defined( OSX ) && defined( __aarch64__ )
|
||||
__builtin_debugtrap();
|
||||
#else
|
||||
asm ( "int $3" );
|
||||
#endif
|
||||
}
|
||||
|
||||
if (GLMDebugChannelMask() & (1<<eGLProfiler))
|
||||
{
|
||||
// we call an obscure GL function which we know has been breakpointed in the OGLP function list
|
||||
static short nada[] = { -1, -1, -1, -1 };
|
||||
glColor4sv( nada );
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define GLMDebugger()
|
||||
#endif
|
||||
|
||||
// helpers for CGLSetOption - no op if no profiler
|
||||
void GLMProfilerClearTrace( void );
|
||||
void GLMProfilerEnableTrace( bool enable );
|
||||
|
||||
// helpers for CGLSetParameter - no op if no profiler
|
||||
void GLMProfilerDumpState( void );
|
||||
|
||||
|
||||
//===============================================================================
|
||||
// classes
|
||||
|
||||
// helper class making function tracking easier to wire up
|
||||
#if GLMDEBUG
|
||||
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
|
||||
#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)
|
||||
|
||||
#ifndef MD5_DIGEST_LENGTH
|
||||
#define MD5_DIGEST_LENGTH 16
|
||||
#endif
|
||||
|
||||
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( const 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
|
||||
std::vector< GLMTextSection > m_sectionTable;
|
||||
};
|
||||
|
||||
#endif
|
||||
1550
external/steamworks/glmgr/glmgrcocoa.mm
vendored
Normal file
1550
external/steamworks/glmgr/glmgrcocoa.mm
vendored
Normal file
File diff suppressed because it is too large
Load Diff
107
external/steamworks/glmgr/glmgrext.cpp
vendored
Normal file
107
external/steamworks/glmgr/glmgrext.cpp
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// glmgrext.h
|
||||
// helper file for extension testing and runtime importing of entry points
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "glmgr.h"
|
||||
|
||||
PFNglColorMaskIndexedEXT pfnglColorMaskIndexedEXT;
|
||||
PFNglEnableIndexedEXT pfnglEnableIndexedEXT;
|
||||
PFNglDisableIndexedEXT pfnglDisableIndexedEXT;
|
||||
PFNglGetFramebufferAttachmentParameteriv pfnglGetFramebufferAttachmentParameteriv;
|
||||
PFNglUniformBufferEXT pfnglUniformBufferEXT;
|
||||
|
||||
// NSSymbol was deprecated in 10.5.
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
void * NSGLGetProcAddress (const char *name)
|
||||
{
|
||||
NSSymbol symbol;
|
||||
char *symbolName = (char *)malloc (strlen (name) + 2);
|
||||
strcpy(symbolName + 1, name);
|
||||
symbolName[0] = '_';
|
||||
symbol = NULL;
|
||||
if (NSIsSymbolNameDefined (symbolName))
|
||||
symbol = NSLookupAndBindSymbol (symbolName);
|
||||
free (symbolName);
|
||||
return symbol ? NSAddressOfSymbol (symbol) : NULL;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
void GLMSetupExtensions( void )
|
||||
{
|
||||
pfnglColorMaskIndexedEXT = (PFNglColorMaskIndexedEXT) NSGLGetProcAddress( "glColorMaskIndexedEXT" );
|
||||
pfnglEnableIndexedEXT = (PFNglEnableIndexedEXT) NSGLGetProcAddress( "glEnableIndexedEXT" );
|
||||
pfnglDisableIndexedEXT = (PFNglDisableIndexedEXT) NSGLGetProcAddress( "glDisableIndexedEXT" );
|
||||
|
||||
pfnglGetFramebufferAttachmentParameteriv = (PFNglGetFramebufferAttachmentParameteriv) NSGLGetProcAddress( "glGetFramebufferAttachmentParameteriv" );
|
||||
|
||||
pfnglUniformBufferEXT = (PFNglUniformBufferEXT) NSGLGetProcAddress( "glUniformBufferEXT" );
|
||||
}
|
||||
|
||||
/*
|
||||
#define INSTANTIATE_GL_IMPORTS
|
||||
#include "glmgr.h" // will include glmgrext.h
|
||||
#undef INSTANTIATE_GL_IMPORTS
|
||||
|
||||
|
||||
// helper class for looking up function names
|
||||
// see http://andrewtolbert.com/svn/personal/OpenGLSuperBible/shared/gltools.cpp
|
||||
// also http://developer.apple.com/mac/library/DOCUMENTATION/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_entrypts/opengl_entrypts.html
|
||||
|
||||
class CFunctionImporter
|
||||
{
|
||||
public:
|
||||
CFBundleRef m_bundle;
|
||||
|
||||
CFunctionImporter( CFStringRef bundleID ) // for example CFSTR("com.apple.OpenGL")
|
||||
{
|
||||
m_bundle = CFBundleGetBundleWithIdentifier( bundleID );
|
||||
if ( m_bundle )
|
||||
CFRetain( m_bundle );
|
||||
}
|
||||
|
||||
~CFunctionImporter()
|
||||
{
|
||||
if( m_bundle )
|
||||
{
|
||||
CFRelease(m_bundle);
|
||||
m_bundle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void *FindFunctionByName(CFStringRef name) // ex CFSTR("glColorMaskedIndexedEXT")
|
||||
{
|
||||
void *result = NULL;
|
||||
if (m_bundle)
|
||||
{
|
||||
result = CFBundleGetFunctionPointerForName(m_bundle, name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void GLMSetupExtensions( void )
|
||||
{
|
||||
CFunctionImporter importer( CFSTR("com.apple.OpenGL") );
|
||||
|
||||
#define DO_IMPORT(name) name = (name##FuncPtr)importer.FindFunctionByName( CFSTR(#name) );
|
||||
|
||||
#ifndef GL_EXT_draw_buffers2
|
||||
// FIXME we're not checking for the extension string yet, we're just grabbing func ptrs
|
||||
DO_IMPORT(glColorMaskIndexedEXT);
|
||||
DO_IMPORT(glEnableIndexedEXT);
|
||||
DO_IMPORT(glDisableIndexedEXT);
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
101
external/steamworks/glmgr/glmgrext.h
vendored
Normal file
101
external/steamworks/glmgr/glmgrext.h
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// glmgrext.h
|
||||
// helper file for extension testing and runtime importing of entry points
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
|
||||
// #define symbol INSTANTIATE_GL_IMPORTS controls whether the following macro "GL_IMPORT" writes externs or writes decls
|
||||
// normally only glmgr.cpp sets that symbol and includes this file
|
||||
|
||||
// to simplify usage, a function ptr type must exist for every entry point, following the name##FuncPtr convention.
|
||||
|
||||
#ifdef INSTANTIATE_GL_IMPORTS
|
||||
#define GL_IMPORT( name ) name##FuncPtr name = 0
|
||||
#else
|
||||
#define GL_IMPORT( name ) extern name##FuncPtr name;
|
||||
#endif
|
||||
|
||||
|
||||
// before declaring each import, check to see if the EXT symbol is in effect,
|
||||
// and if so, don't do it!
|
||||
|
||||
#ifndef GL_EXT_draw_buffers2
|
||||
typedef void (* glColorMaskIndexedEXTFuncPtr) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
|
||||
typedef void (* glEnableIndexedEXTFuncPtr) (GLenum target, GLuint index);
|
||||
typedef void (* glDisableIndexedEXTFuncPtr) (GLenum target, GLuint index);
|
||||
|
||||
GL_IMPORT(glColorMaskIndexedEXT);
|
||||
GL_IMPORT(glEnableIndexedEXT);
|
||||
GL_IMPORT(glDisableIndexedEXT);
|
||||
#endif
|
||||
|
||||
#ifndef GL_EXT_framebuffer_sRGB
|
||||
#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
|
||||
#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
|
||||
#endif
|
||||
|
||||
#ifndef ARB_texture_rg
|
||||
#define GL_COMPRESSED_RED 0x8225
|
||||
#define GL_COMPRESSED_RG 0x8226
|
||||
#define GL_RG 0x8227
|
||||
#define GL_RG_INTEGER 0x8228
|
||||
#define GL_R8 0x8229
|
||||
#define GL_R16 0x822A
|
||||
#define GL_RG8 0x822B
|
||||
#define GL_RG16 0x822C
|
||||
#define GL_R16F 0x822D
|
||||
#define GL_R32F 0x822E
|
||||
#define GL_RG16F 0x822F
|
||||
#define GL_RG32F 0x8230
|
||||
#define GL_R8I 0x8231
|
||||
#define GL_R8UI 0x8232
|
||||
#define GL_R16I 0x8233
|
||||
#define GL_R16UI 0x8234
|
||||
#define GL_R32I 0x8235
|
||||
#define GL_R32UI 0x8236
|
||||
#define GL_RG8I 0x8237
|
||||
#define GL_RG8UI 0x8238
|
||||
#define GL_RG16I 0x8239
|
||||
#define GL_RG16UI 0x823A
|
||||
#define GL_RG32I 0x823B
|
||||
#define GL_RG32UI 0x823C
|
||||
#endif
|
||||
|
||||
#ifndef GL_EXT_bindable_uniform
|
||||
#define GL_UNIFORM_BUFFER_EXT 0x8DEE
|
||||
#endif
|
||||
|
||||
// unpublished extension enums (thus the "X")
|
||||
|
||||
// from EXT_framebuffer_multisample_blit_scaled..
|
||||
#define XGL_SCALED_RESOLVE_FASTEST_EXT 0x90BA
|
||||
#define XGL_SCALED_RESOLVE_NICEST_EXT 0x90BB
|
||||
|
||||
|
||||
void * NSGLGetProcAddress (const char *name);
|
||||
|
||||
// call this to find all the entry points.
|
||||
void GLMSetupExtensions( void );
|
||||
|
||||
|
||||
|
||||
typedef void (*PFNglColorMaskIndexedEXT)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
|
||||
typedef void (*PFNglEnableIndexedEXT)(GLenum target, GLuint index);
|
||||
typedef void (*PFNglDisableIndexedEXT)(GLenum target, GLuint index);
|
||||
typedef void (*PFNglUniformBufferEXT)(GLuint program, GLint location, GLuint buffer);
|
||||
|
||||
extern PFNglColorMaskIndexedEXT pfnglColorMaskIndexedEXT;
|
||||
extern PFNglEnableIndexedEXT pfnglEnableIndexedEXT;
|
||||
extern PFNglDisableIndexedEXT pfnglDisableIndexedEXT;
|
||||
extern PFNglUniformBufferEXT pfnglUniformBufferEXT;
|
||||
|
||||
|
||||
typedef void (*PFNglGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
|
||||
extern PFNglGetFramebufferAttachmentParameteriv pfnglGetFramebufferAttachmentParameteriv;
|
||||
|
||||
523
external/steamworks/glmgr/imageformat.h
vendored
Normal file
523
external/steamworks/glmgr/imageformat.h
vendored
Normal file
@@ -0,0 +1,523 @@
|
||||
//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef IMAGEFORMAT_H
|
||||
#define IMAGEFORMAT_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
enum NormalDecodeMode_t
|
||||
{
|
||||
NORMAL_DECODE_NONE = 0,
|
||||
NORMAL_DECODE_ATI2N = 1,
|
||||
NORMAL_DECODE_ATI2N_ALPHA = 2
|
||||
};
|
||||
|
||||
// Forward declaration
|
||||
#ifdef _WIN32
|
||||
typedef enum _D3DFORMAT D3DFORMAT;
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The various image format types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// don't bitch that inline functions aren't used!!!!
|
||||
#pragma warning(disable : 4514)
|
||||
|
||||
enum ImageFormat
|
||||
{
|
||||
IMAGE_FORMAT_UNKNOWN = -1,
|
||||
IMAGE_FORMAT_RGBA8888 = 0,
|
||||
IMAGE_FORMAT_ABGR8888,
|
||||
IMAGE_FORMAT_RGB888,
|
||||
IMAGE_FORMAT_BGR888,
|
||||
IMAGE_FORMAT_RGB565,
|
||||
IMAGE_FORMAT_I8,
|
||||
IMAGE_FORMAT_IA88,
|
||||
IMAGE_FORMAT_P8,
|
||||
IMAGE_FORMAT_A8,
|
||||
IMAGE_FORMAT_RGB888_BLUESCREEN,
|
||||
IMAGE_FORMAT_BGR888_BLUESCREEN,
|
||||
IMAGE_FORMAT_ARGB8888,
|
||||
IMAGE_FORMAT_BGRA8888,
|
||||
IMAGE_FORMAT_DXT1,
|
||||
IMAGE_FORMAT_DXT3,
|
||||
IMAGE_FORMAT_DXT5,
|
||||
IMAGE_FORMAT_BGRX8888,
|
||||
IMAGE_FORMAT_BGR565,
|
||||
IMAGE_FORMAT_BGRX5551,
|
||||
IMAGE_FORMAT_BGRA4444,
|
||||
IMAGE_FORMAT_DXT1_ONEBITALPHA,
|
||||
IMAGE_FORMAT_BGRA5551,
|
||||
IMAGE_FORMAT_UV88,
|
||||
IMAGE_FORMAT_UVWQ8888,
|
||||
IMAGE_FORMAT_RGBA16161616F,
|
||||
IMAGE_FORMAT_RGBA16161616,
|
||||
IMAGE_FORMAT_UVLX8888,
|
||||
IMAGE_FORMAT_R32F, // Single-channel 32-bit floating point
|
||||
IMAGE_FORMAT_RGB323232F,
|
||||
IMAGE_FORMAT_RGBA32323232F,
|
||||
|
||||
// Depth-stencil texture formats for shadow depth mapping
|
||||
IMAGE_FORMAT_NV_DST16, //
|
||||
IMAGE_FORMAT_NV_DST24, //
|
||||
IMAGE_FORMAT_NV_INTZ, // Vendor-specific depth-stencil texture
|
||||
IMAGE_FORMAT_NV_RAWZ, // formats for shadow depth mapping
|
||||
IMAGE_FORMAT_ATI_DST16, //
|
||||
IMAGE_FORMAT_ATI_DST24, //
|
||||
IMAGE_FORMAT_NV_NULL, // Dummy format which takes no video memory
|
||||
|
||||
// Compressed normal map formats
|
||||
IMAGE_FORMAT_ATI2N, // One-surface ATI2N / DXN format
|
||||
IMAGE_FORMAT_ATI1N, // Two-surface ATI1N format
|
||||
|
||||
#if defined( _X360 )
|
||||
// Depth-stencil texture formats
|
||||
IMAGE_FORMAT_X360_DST16,
|
||||
IMAGE_FORMAT_X360_DST24,
|
||||
IMAGE_FORMAT_X360_DST24F,
|
||||
// supporting these specific formats as non-tiled for procedural cpu access
|
||||
IMAGE_FORMAT_LINEAR_BGRX8888,
|
||||
IMAGE_FORMAT_LINEAR_RGBA8888,
|
||||
IMAGE_FORMAT_LINEAR_ABGR8888,
|
||||
IMAGE_FORMAT_LINEAR_ARGB8888,
|
||||
IMAGE_FORMAT_LINEAR_BGRA8888,
|
||||
IMAGE_FORMAT_LINEAR_RGB888,
|
||||
IMAGE_FORMAT_LINEAR_BGR888,
|
||||
IMAGE_FORMAT_LINEAR_BGRX5551,
|
||||
IMAGE_FORMAT_LINEAR_I8,
|
||||
IMAGE_FORMAT_LINEAR_RGBA16161616,
|
||||
|
||||
IMAGE_FORMAT_LE_BGRX8888,
|
||||
IMAGE_FORMAT_LE_BGRA8888,
|
||||
#endif
|
||||
|
||||
NUM_IMAGE_FORMATS
|
||||
};
|
||||
|
||||
#if defined( POSIX ) || defined( DX_TO_GL_ABSTRACTION )
|
||||
typedef enum _D3DFORMAT
|
||||
{
|
||||
D3DFMT_INDEX16,
|
||||
D3DFMT_D16,
|
||||
D3DFMT_D24S8,
|
||||
D3DFMT_A8R8G8B8,
|
||||
D3DFMT_A4R4G4B4,
|
||||
D3DFMT_X8R8G8B8,
|
||||
D3DFMT_R5G6R5,
|
||||
D3DFMT_X1R5G5B5,
|
||||
D3DFMT_A1R5G5B5,
|
||||
D3DFMT_L8,
|
||||
D3DFMT_A8L8,
|
||||
D3DFMT_A,
|
||||
D3DFMT_DXT1,
|
||||
D3DFMT_DXT3,
|
||||
D3DFMT_DXT5,
|
||||
D3DFMT_V8U8,
|
||||
D3DFMT_Q8W8V8U8,
|
||||
D3DFMT_X8L8V8U8,
|
||||
D3DFMT_A16B16G16R16F,
|
||||
D3DFMT_A16B16G16R16,
|
||||
D3DFMT_R32F,
|
||||
D3DFMT_A32B32G32R32F,
|
||||
D3DFMT_R8G8B8,
|
||||
D3DFMT_D24X4S4,
|
||||
D3DFMT_A8,
|
||||
D3DFMT_R5G6B5,
|
||||
D3DFMT_D15S1,
|
||||
D3DFMT_D24X8,
|
||||
D3DFMT_VERTEXDATA,
|
||||
D3DFMT_INDEX32,
|
||||
|
||||
// adding fake D3D format names for the vendor specific ones (eases debugging/logging)
|
||||
|
||||
// NV shadow depth tex
|
||||
D3DFMT_NV_INTZ = 0x5a544e49, // MAKEFOURCC('I','N','T','Z')
|
||||
D3DFMT_NV_RAWZ = 0x5a574152, // MAKEFOURCC('R','A','W','Z')
|
||||
|
||||
// NV null tex
|
||||
D3DFMT_NV_NULL = 0x4c4c554e, // MAKEFOURCC('N','U','L','L')
|
||||
|
||||
// ATI shadow depth tex
|
||||
D3DFMT_ATI_D16 = 0x36314644, // MAKEFOURCC('D','F','1','6')
|
||||
D3DFMT_ATI_D24S8 = 0x34324644, // MAKEFOURCC('D','F','2','4')
|
||||
|
||||
// ATI 1N and 2N compressed tex
|
||||
D3DFMT_ATI_2N = 0x32495441, // MAKEFOURCC('A', 'T', 'I', '2')
|
||||
D3DFMT_ATI_1N = 0x31495441, // MAKEFOURCC('A', 'T', 'I', '1')
|
||||
|
||||
D3DFMT_UNKNOWN
|
||||
} D3DFORMAT;
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Color structures
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct BGRA8888_t
|
||||
{
|
||||
unsigned char b; // change the order of names to change the
|
||||
unsigned char g; // order of the output ARGB or BGRA, etc...
|
||||
unsigned char r; // Last one is MSB, 1st is LSB.
|
||||
unsigned char a;
|
||||
inline BGRA8888_t& operator=( const BGRA8888_t& in )
|
||||
{
|
||||
*( unsigned int * )this = *( unsigned int * )∈
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct RGBA8888_t
|
||||
{
|
||||
unsigned char r; // change the order of names to change the
|
||||
unsigned char g; // order of the output ARGB or BGRA, etc...
|
||||
unsigned char b; // Last one is MSB, 1st is LSB.
|
||||
unsigned char a;
|
||||
inline RGBA8888_t& operator=( const BGRA8888_t& in )
|
||||
{
|
||||
r = in.r;
|
||||
g = in.g;
|
||||
b = in.b;
|
||||
a = in.a;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct RGB888_t
|
||||
{
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
inline RGB888_t& operator=( const BGRA8888_t& in )
|
||||
{
|
||||
r = in.r;
|
||||
g = in.g;
|
||||
b = in.b;
|
||||
return *this;
|
||||
}
|
||||
inline bool operator==( const RGB888_t& in ) const
|
||||
{
|
||||
return ( r == in.r ) && ( g == in.g ) && ( b == in.b );
|
||||
}
|
||||
inline bool operator!=( const RGB888_t& in ) const
|
||||
{
|
||||
return ( r != in.r ) || ( g != in.g ) || ( b != in.b );
|
||||
}
|
||||
};
|
||||
|
||||
struct BGR888_t
|
||||
{
|
||||
unsigned char b;
|
||||
unsigned char g;
|
||||
unsigned char r;
|
||||
inline BGR888_t& operator=( const BGRA8888_t& in )
|
||||
{
|
||||
r = in.r;
|
||||
g = in.g;
|
||||
b = in.b;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// 360 uses this structure for x86 dxt decoding
|
||||
#if defined( _X360 )
|
||||
#pragma bitfield_order( push, lsb_to_msb )
|
||||
#endif
|
||||
struct BGR565_t
|
||||
{
|
||||
unsigned short b : 5; // order of names changes
|
||||
unsigned short g : 6; // byte order of output to 32 bit
|
||||
unsigned short r : 5;
|
||||
inline BGR565_t& operator=( const BGRA8888_t& in )
|
||||
{
|
||||
r = in.r >> 3;
|
||||
g = in.g >> 2;
|
||||
b = in.b >> 3;
|
||||
return *this;
|
||||
}
|
||||
inline BGR565_t &Set( int red, int green, int blue )
|
||||
{
|
||||
r = red >> 3;
|
||||
g = green >> 2;
|
||||
b = blue >> 3;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
#if defined( _X360 )
|
||||
#pragma bitfield_order( pop )
|
||||
#endif
|
||||
|
||||
struct BGRA5551_t
|
||||
{
|
||||
unsigned short b : 5; // order of names changes
|
||||
unsigned short g : 5; // byte order of output to 32 bit
|
||||
unsigned short r : 5;
|
||||
unsigned short a : 1;
|
||||
inline BGRA5551_t& operator=( const BGRA8888_t& in )
|
||||
{
|
||||
r = in.r >> 3;
|
||||
g = in.g >> 3;
|
||||
b = in.b >> 3;
|
||||
a = in.a >> 7;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct BGRA4444_t
|
||||
{
|
||||
unsigned short b : 4; // order of names changes
|
||||
unsigned short g : 4; // byte order of output to 32 bit
|
||||
unsigned short r : 4;
|
||||
unsigned short a : 4;
|
||||
inline BGRA4444_t& operator=( const BGRA8888_t& in )
|
||||
{
|
||||
r = in.r >> 4;
|
||||
g = in.g >> 4;
|
||||
b = in.b >> 4;
|
||||
a = in.a >> 4;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct RGBX5551_t
|
||||
{
|
||||
unsigned short r : 5;
|
||||
unsigned short g : 5;
|
||||
unsigned short b : 5;
|
||||
unsigned short x : 1;
|
||||
inline RGBX5551_t& operator=( const BGRA8888_t& in )
|
||||
{
|
||||
r = in.r >> 3;
|
||||
g = in.g >> 3;
|
||||
b = in.b >> 3;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// some important constants
|
||||
//-----------------------------------------------------------------------------
|
||||
#define ARTWORK_GAMMA ( 2.2f )
|
||||
#define IMAGE_MAX_DIM ( 2048 )
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// information about each image format
|
||||
//-----------------------------------------------------------------------------
|
||||
struct ImageFormatInfo_t
|
||||
{
|
||||
char* m_pName;
|
||||
int m_NumBytes;
|
||||
int m_NumRedBits;
|
||||
int m_NumGreeBits;
|
||||
int m_NumBlueBits;
|
||||
int m_NumAlphaBits;
|
||||
bool m_IsCompressed:1;
|
||||
bool m_IsFloat:1;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Various methods related to pixelmaps and color formats
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace ImageLoader
|
||||
{
|
||||
|
||||
bool GetInfo( const char *fileName, int *width, int *height, enum ImageFormat *imageFormat, float *sourceGamma );
|
||||
int GetMemRequired( int width, int height, int depth, ImageFormat imageFormat, bool mipmap );
|
||||
int GetMipMapLevelByteOffset( int width, int height, enum ImageFormat imageFormat, int skipMipLevels, int nDepth = 1 );
|
||||
void GetMipMapLevelDimensions( int *width, int *height, int skipMipLevels );
|
||||
int GetNumMipMapLevels( int width, int height, int depth = 1 );
|
||||
bool Load( unsigned char *imageData, const char *fileName, int width, int height, enum ImageFormat imageFormat, float targetGamma, bool mipmap );
|
||||
bool Load( unsigned char *imageData, FILE *fp, int width, int height,
|
||||
enum ImageFormat imageFormat, float targetGamma, bool mipmap );
|
||||
|
||||
// convert from any image format to any other image format.
|
||||
// return false if the conversion cannot be performed.
|
||||
// Strides denote the number of bytes per each line,
|
||||
// by default assumes width * # of bytes per pixel
|
||||
bool ConvertImageFormat( const unsigned char *src, enum ImageFormat srcImageFormat,
|
||||
unsigned char *dst, enum ImageFormat dstImageFormat,
|
||||
int width, int height, int srcStride = 0, int dstStride = 0 );
|
||||
|
||||
// must be used in conjunction with ConvertImageFormat() to pre-swap and post-swap
|
||||
void PreConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 );
|
||||
void PostConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 );
|
||||
void ByteSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 );
|
||||
bool IsFormatValidForConversion( ImageFormat fmt );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// convert back and forth from D3D format to ImageFormat, regardless of
|
||||
// whether it's supported or not
|
||||
//-----------------------------------------------------------------------------
|
||||
ImageFormat D3DFormatToImageFormat( D3DFORMAT format );
|
||||
D3DFORMAT ImageFormatToD3DFormat( ImageFormat format );
|
||||
|
||||
// Flags for ResampleRGBA8888
|
||||
enum
|
||||
{
|
||||
RESAMPLE_NORMALMAP = 0x1,
|
||||
RESAMPLE_ALPHATEST = 0x2,
|
||||
RESAMPLE_NICE_FILTER = 0x4,
|
||||
RESAMPLE_CLAMPS = 0x8,
|
||||
RESAMPLE_CLAMPT = 0x10,
|
||||
RESAMPLE_CLAMPU = 0x20,
|
||||
};
|
||||
|
||||
struct ResampleInfo_t
|
||||
{
|
||||
|
||||
ResampleInfo_t() : m_nFlags(0), m_flAlphaThreshhold(0.4f), m_flAlphaHiFreqThreshhold(0.4f), m_nSrcDepth(1), m_nDestDepth(1)
|
||||
{
|
||||
m_flColorScale[0] = 1.0f, m_flColorScale[1] = 1.0f, m_flColorScale[2] = 1.0f, m_flColorScale[3] = 1.0f;
|
||||
m_flColorGoal[0] = 0.0f, m_flColorGoal[1] = 0.0f, m_flColorGoal[2] = 0.0f, m_flColorGoal[3] = 0.0f;
|
||||
}
|
||||
|
||||
unsigned char *m_pSrc;
|
||||
unsigned char *m_pDest;
|
||||
|
||||
int m_nSrcWidth;
|
||||
int m_nSrcHeight;
|
||||
int m_nSrcDepth;
|
||||
|
||||
int m_nDestWidth;
|
||||
int m_nDestHeight;
|
||||
int m_nDestDepth;
|
||||
|
||||
float m_flSrcGamma;
|
||||
float m_flDestGamma;
|
||||
|
||||
float m_flColorScale[4]; // Color scale factors RGBA
|
||||
float m_flColorGoal[4]; // Color goal values RGBA DestColor = ColorGoal + scale * (SrcColor - ColorGoal)
|
||||
|
||||
float m_flAlphaThreshhold;
|
||||
float m_flAlphaHiFreqThreshhold;
|
||||
|
||||
int m_nFlags;
|
||||
};
|
||||
|
||||
bool ResampleRGBA8888( const ResampleInfo_t &info );
|
||||
bool ResampleRGBA16161616( const ResampleInfo_t &info );
|
||||
bool ResampleRGB323232F( const ResampleInfo_t &info );
|
||||
|
||||
void ConvertNormalMapRGBA8888ToDUDVMapUVLX8888( const unsigned char *src, int width, int height, unsigned char *dst_ );
|
||||
void ConvertNormalMapRGBA8888ToDUDVMapUVWQ8888( const unsigned char *src, int width, int height, unsigned char *dst_ );
|
||||
void ConvertNormalMapRGBA8888ToDUDVMapUV88( const unsigned char *src, int width, int height, unsigned char *dst_ );
|
||||
void ConvertNormalMapARGB8888ToDXT5GA( const unsigned char *src, unsigned char *dst, int width, int height );
|
||||
|
||||
void ConvertIA88ImageToNormalMapRGBA8888( const unsigned char *src, int width,
|
||||
int height, unsigned char *dst,
|
||||
float bumpScale );
|
||||
|
||||
void NormalizeNormalMapRGBA8888( unsigned char *src, int numTexels );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gamma correction
|
||||
//-----------------------------------------------------------------------------
|
||||
void GammaCorrectRGBA8888( unsigned char *src, unsigned char* dst,
|
||||
int width, int height, int depth, float srcGamma, float dstGamma );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Makes a gamma table
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConstructGammaTable( unsigned char* pTable, float srcGamma, float dstGamma );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gamma corrects using a previously constructed gamma table
|
||||
//-----------------------------------------------------------------------------
|
||||
void GammaCorrectRGBA8888( unsigned char* pSrc, unsigned char* pDst,
|
||||
int width, int height, int depth, unsigned char* pGammaTable );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Generates a number of mipmap levels
|
||||
//-----------------------------------------------------------------------------
|
||||
void GenerateMipmapLevels( unsigned char* pSrc, unsigned char* pDst, int width,
|
||||
int height, int depth, ImageFormat imageFormat, float srcGamma, float dstGamma,
|
||||
int numLevels = 0 );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// operations on square images (src and dst can be the same)
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RotateImageLeft( const unsigned char *src, unsigned char *dst,
|
||||
int widthHeight, ImageFormat imageFormat );
|
||||
bool RotateImage180( const unsigned char *src, unsigned char *dst,
|
||||
int widthHeight, ImageFormat imageFormat );
|
||||
bool FlipImageVertically( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride = 0 );
|
||||
bool FlipImageHorizontally( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride = 0 );
|
||||
bool SwapAxes( unsigned char *src,
|
||||
int widthHeight, ImageFormat imageFormat );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns info about each image format
|
||||
//-----------------------------------------------------------------------------
|
||||
ImageFormatInfo_t const& ImageFormatInfo( ImageFormat fmt );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the name of the image format
|
||||
//-----------------------------------------------------------------------------
|
||||
inline char const* GetName( ImageFormat fmt )
|
||||
{
|
||||
return ImageFormatInfo(fmt).m_pName;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the size of the image format in bytes
|
||||
//-----------------------------------------------------------------------------
|
||||
inline int SizeInBytes( ImageFormat fmt )
|
||||
{
|
||||
return ImageFormatInfo(fmt).m_NumBytes;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Does the image format support transparency?
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool IsTransparent( ImageFormat fmt )
|
||||
{
|
||||
return ImageFormatInfo(fmt).m_NumAlphaBits > 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Is the image format compressed?
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool IsCompressed( ImageFormat fmt )
|
||||
{
|
||||
return ImageFormatInfo(fmt).m_IsCompressed;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Is any channel > 8 bits?
|
||||
//-----------------------------------------------------------------------------
|
||||
inline bool HasChannelLargerThan8Bits( ImageFormat fmt )
|
||||
{
|
||||
ImageFormatInfo_t info = ImageFormatInfo(fmt);
|
||||
return ( info.m_NumRedBits > 8 || info.m_NumGreeBits > 8 || info.m_NumBlueBits > 8 || info.m_NumAlphaBits > 8 );
|
||||
}
|
||||
|
||||
inline bool IsFloatFormat( ImageFormat fmt )
|
||||
{
|
||||
return ( fmt == IMAGE_FORMAT_RGBA16161616F ) ||
|
||||
( fmt == IMAGE_FORMAT_R32F ) ||
|
||||
( fmt == IMAGE_FORMAT_RGB323232F ) ||
|
||||
( fmt == IMAGE_FORMAT_RGBA32323232F );
|
||||
}
|
||||
|
||||
} // end namespace ImageLoader
|
||||
|
||||
|
||||
#endif // IMAGEFORMAT_H
|
||||
1252
external/steamworks/glmgr/mathlite.cpp
vendored
Normal file
1252
external/steamworks/glmgr/mathlite.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4437
external/steamworks/glmgr/mathlite.h
vendored
Normal file
4437
external/steamworks/glmgr/mathlite.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
external/steamworks/glmgr/readme.txt
vendored
Normal file
11
external/steamworks/glmgr/readme.txt
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
================================================================
|
||||
|
||||
Copyright © 1996-2011, Valve Corporation, All rights reserved.
|
||||
|
||||
================================================================
|
||||
|
||||
OSX DirectX to OpenGL Conversion Library
|
||||
|
||||
Contains all support files required to assist in converting DirectX applications to OpenGL on OSX. For reference,
|
||||
this library can be enabled in the Steamworks Example by building with the compile time flag DX9MODE=1.
|
||||
|
||||
Reference in New Issue
Block a user