You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLPlatform.hpp

524 lines
15 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Description : Platform specific DXGL requirements implementation
#ifndef __GLPLATFORM__
#define __GLPLATFORM__
namespace NCryOpenGL
{
enum ELogSeverity
{
eLS_Info,
eLS_Warning,
eLS_Error
};
}
#define CUSTOM_SCOPED_PROFILE(_Name)
#if defined(OPENGL)
#include "GLCryPlatform.hpp"
#elif defined(WIN32)
#include "../Standalone/GLWinPlatform.hpp"
#elif defined(LINUX)
#include "../Standalone/GLLinuxPlatform.hpp"
#else
#error "Platform is not supported"
#endif
#define DXGL_PROFILING 0
#if defined(AZ_COMPILER_MSVC)
#define _DXGL_LOG_STRINGIFY_(x) #x
#define _DXGL_LOG_STRINGIFY(x) _DXGL_LOG_STRINGIFY_(x)
#define _DXGL_LOG_MSG(_TEXT, _FILE, _LINE, _FUNC) "DXGL: " _TEXT " : [@" _FUNC "] " _FILE "(" _LINE ")"
#define DXGL_LOG_MSG(_TEXT) _DXGL_LOG_MSG(_TEXT, __FILE__, _DXGL_LOG_STRINGIFY(__LINE__), __FUNCSIG__)
#else
#define _DXGL_LOG_MSG(_TEXT, _FILE, _FUNC) "DXGL: " _TEXT " : [@" _FUNC "] " _FILE "(%d)"
#define DXGL_LOG_MSG(_TEXT) _DXGL_LOG_MSG(_TEXT, __FILE__, "?") // GCC can't resolve __FUNCTION__ in the preprocessor
#endif
#if defined(_MSC_VER)
#define DXGL_WARNING(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Warning, DXGL_LOG_MSG(_Format), __VA_ARGS__)
#define DXGL_ERROR(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Error, DXGL_LOG_MSG(_Format), __VA_ARGS__)
#define DXGL_INFO(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Info, DXGL_LOG_MSG(_Format), __VA_ARGS__)
#else
#define DXGL_WARNING(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Warning, DXGL_LOG_MSG(_Format), ##__VA_ARGS__, __LINE__)
#define DXGL_ERROR(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Error, DXGL_LOG_MSG(_Format), ##__VA_ARGS__, __LINE__)
#define DXGL_INFO(_Format, ...) NCryOpenGL::LogMessage(NCryOpenGL::eLS_Info, DXGL_LOG_MSG(_Format), ##__VA_ARGS__, __LINE__)
#endif
#define DXGL_NOT_IMPLEMENTED NCryOpenGL::BreakUnique(__FILE__, __LINE__, __func__);
#define DXGL_TODO(_DESC)
#define DXGL_ARRAY_SIZE(_Array) (sizeof(_Array) / sizeof(_Array[0]))
#define _DXGL_QUOTE(X) #X
#define DXGL_QUOTE(X) _DXGL_QUOTE(X)
#define DXGL_CAT(_Left, _Right) _Left ## _Right
#define _DXGL_IF_0(...)
#define _DXGL_IF_1(...) __VA_ARGS__
#define DXGL_IF(_Condition) DXGL_CAT(_DXGL_IF_, _Condition)
#define DXGL_DECLARE_PTR(_Qualifier, _TypeName) \
_Qualifier _TypeName; \
typedef _smart_ptr<_TypeName> _TypeName ## Ptr;
#define DXGL_DECLARE_REF_COUNTED(_Qualifier, _TypeName) \
DXGL_DECLARE_PTR(_Qualifier, _TypeName) \
_Qualifier _TypeName: public NCryOpenGL::SRefCounted < _TypeName >
namespace NCryOpenGL
{
template <typename T>
struct SRefCounted
{
uint32 m_uRefCnt;
SRefCounted()
: m_uRefCnt(0)
{
}
void AddRef()
{
++m_uRefCnt;
}
void Release()
{
if (--m_uRefCnt == 0)
{
delete static_cast<T*>(this);
}
}
};
struct SSpinlockBitMaskWord
{
typedef LONG Word;
enum
{
BIT_SIZE = sizeof(Word) * 8
};
volatile Word m_aMask;
void Set(Word kNewValue)
{
Exchange(&m_aMask, kNewValue);
}
Word Get() const
{
return CompareExchange(const_cast<Word*>(&m_aMask), 0, 0);
}
bool Set(uint32 uIndex, bool bFlag)
{
while (true)
{
Word kOld(m_aMask);
Word uFlagMask(1 << uIndex);
Word kNew(bFlag ? (kOld | uFlagMask) : (kOld & ~uFlagMask));
if (CompareExchange(&m_aMask, kNew, kOld) == kOld)
{
return (kOld & uFlagMask) != 0;
}
}
}
bool Get(uint32 uIndex) const
{
assert(uIndex <= BIT_SIZE);
return ((m_aMask >> uIndex) & 1) != 0;
}
};
struct SUnsafeBitMaskWord
{
typedef uint32 Word;
enum
{
BIT_SIZE = sizeof(Word) * 8
};
Word m_aMask;
void Set(Word kNewValue)
{
m_aMask = kNewValue;
}
Word Get() const
{
return m_aMask;
}
bool Set(uint32 uIndex, bool bFlag)
{
assert(uIndex <= BIT_SIZE);
Word uFlagMask(1 << uIndex);
Word kOld(m_aMask);
m_aMask = bFlag ? (kOld | uFlagMask) : (kOld & ~uFlagMask);
return (kOld & uFlagMask) != 0;
}
bool Get(uint32 uIndex) const
{
assert(uIndex <= BIT_SIZE);
return ((m_aMask >> uIndex) & 1) != 0;
}
};
template <uint32 uNumWords, typename BitMaskWord>
struct SBitMaskMultiWord
{
typedef BitMaskWord Word;
Word m_akWords[uNumWords];
bool Set(uint32 uIndex, bool bFlag)
{
return m_akWords[uIndex / Word::BIT_SIZE].Set(uIndex % Word::BIT_SIZE, bFlag);
}
bool Get(uint32 uIndex) const
{
return m_akWords[uIndex / Word::BIT_SIZE].Get(uIndex % Word::BIT_SIZE);
}
};
template <uint32 uNumWords, typename BitMaskWord>
struct SBitMaskImpl
{
typedef SBitMaskMultiWord<uNumWords, BitMaskWord> Type;
typedef typename BitMaskWord::Word Word;
static void Init(Type* pMask, bool bValue, Word kUsedMask)
{
memset(pMask->m_akWords, bValue ? (Word) ~0 : (Word)0, sizeof(Word) * (uNumWords - 1));
pMask->m_akWords[uNumWords - 1].m_aMask = bValue ? kUsedMask : (Word)0;
}
static void SetZero(Type* pMask)
{
for (uint32 uPosition = 0; uPosition < uNumWords; ++uPosition)
{
pMask->m_akWords[uPosition].Set((Word)0);
}
}
static void SetOne(Type* pMask, Word kUsedMask)
{
for (uint32 uPosition = 0; uPosition < uNumWords - 1; ++uPosition)
{
pMask->m_akWords[uPosition].Set(~(Word)0);
}
pMask->m_akWords[uNumWords - 1].Set(kUsedMask);
}
static bool IsZero(Type* pMask, Word kUsedMask)
{
for (uint32 uPosition = 0; uPosition < uNumWords - 1; ++uPosition)
{
if (pMask->m_akWords[uPosition].Get() != (Word)0)
{
return false;
}
}
return (pMask->m_akWords[uNumWords - 1].Get() & kUsedMask) == (Word)0;
}
static bool IsOne(Type* pMask, Word kUsedMask)
{
for (uint32 uPosition = 0; uPosition < uNumWords - 1; ++uPosition)
{
if (pMask->m_akWords[uPosition].Get() != ~(Word)0)
{
return false;
}
}
return (pMask->m_akWords[uNumWords - 1].Get() & kUsedMask) == kUsedMask;
}
static void BitwiseOr(BitMaskWord* pResult, const BitMaskWord& kLeft, const BitMaskWord& kRight)
{
for (uint32 uIndex = 0; uIndex < uNumWords; ++uIndex)
{
pResult->m_akWords[uIndex].Set(kLeft.m_akWords[uIndex].Get() | kRight.m_akWords[uIndex].Get());
}
}
static void BitwiseAnd(BitMaskWord* pResult, const BitMaskWord& kLeft, const BitMaskWord& kRight)
{
for (uint32 uIndex = 0; uIndex < uNumWords; ++uIndex)
{
pResult->m_akWords[uIndex].Set(kLeft.m_akWords[uIndex].Get() & kRight.m_akWords[uIndex].Get());
}
}
static bool Equals(const BitMaskWord& kLeft, const BitMaskWord& kRight)
{
for (uint32 uIndex = 0; uIndex < uNumWords; ++uIndex)
{
if (kLeft.m_akWords[uIndex].Get() != kRight.m_akWords[uIndex].Get())
{
return false;
}
}
return true;
}
static void Copy(BitMaskWord* pDestination, const BitMaskWord& kSource)
{
for (uint32 uIndex = 0; uIndex < uNumWords; ++uIndex)
{
pDestination->m_akWords[uIndex].Set(kSource.m_akWords[uIndex].Get());
}
}
};
template <typename BitMaskWord>
struct SBitMaskImpl<1, BitMaskWord>
{
typedef BitMaskWord Type;
typedef typename BitMaskWord::Word Word;
static void Init(Type* pMask, bool bValue, Word kUsedMask)
{
pMask->m_aMask = bValue ? kUsedMask : (Word)0;
}
static void SetZero(Type* pMask)
{
pMask->Set((Word)0);
}
static void SetOne(Type* pMask, Word kUsedMask)
{
pMask->Set(kUsedMask);
}
static bool IsZero(const Type* pMask, Word kUsedMask)
{
return (pMask->Get() & kUsedMask) == (Word)0;
}
static bool IsOne(const Type* pMask, Word kUsedMask)
{
return (pMask->Get() & kUsedMask) == kUsedMask;
}
static void BitwiseOr(Type* pResult, const Type& kLeft, const Type& kRight)
{
pResult->Set(kLeft.Get() | kRight.Get());
}
static void BitwiseAnd(Type* pResult, const Type& kLeft, const Type& kRight)
{
pResult->Set(kLeft.Get() & kRight.Get());
}
static bool Equals(const Type& kLeft, const Type& kRight)
{
return kLeft.Get() == kRight.Get();
}
static void Copy(Type* pDestination, const Type& kSource)
{
pDestination->Set(kSource.Get());
}
};
template <uint32 uSize, typename BitMaskWord>
struct SBitMask
: SBitMaskImpl<(uSize + BitMaskWord::BIT_SIZE - 1) / BitMaskWord::BIT_SIZE, BitMaskWord>::Type
{
typedef SBitMaskImpl<(uSize + BitMaskWord::BIT_SIZE - 1) / BitMaskWord::BIT_SIZE, BitMaskWord> Impl;
typedef typename BitMaskWord::Word Word;
enum
{
USED_MASK = ~(~(Word)0 << uSize % BitMaskWord::BIT_SIZE)
};
// The following methods are not thread safe regardless of the BitMaskWord type
SBitMask(bool bInitValue = false)
{
Impl::Init(this, bInitValue, (Word)USED_MASK);
}
SBitMask(const SBitMask& kOther)
{
Impl::Copy(this, kOther);
}
void SetZero()
{
return Impl::SetZero(this);
}
void SetOne()
{
return Impl::SetOne(this, (Word)USED_MASK);
}
bool IsZero() const
{
return Impl::IsZero(this, (Word)USED_MASK);
}
bool IsOne() const
{
return Impl::IsOne(this, (Word)USED_MASK);
}
SBitMask& operator|=(const SBitMask& kOther)
{
Impl::BitwiseOr(this, *this, kOther);
return *this;
}
SBitMask& operator&=(const SBitMask& kOther)
{
Impl::BitwiseAnd(this, *this, kOther);
return *this;
}
SBitMask operator|(const SBitMask& kOther) const
{
SBitMask kResult;
Impl::BitwiseOr(&kResult, *this, kOther);
return kResult;
}
SBitMask operator&(const SBitMask& kOther) const
{
SBitMask kResult;
Impl::BitwiseAnd(&kResult, *this, kOther);
return kResult;
}
bool operator==(const SBitMask& kOther) const
{
return Impl::Equals(*this, kOther);
}
bool operator!=(const SBitMask& kOther) const
{
return !Impl::Equals(*this, kOther);
}
SBitMask& operator=(const SBitMask& kOther)
{
Impl::Copy(this, kOther);
return *this;
}
};
inline void* CreateTLS()
{
#if defined(WIN32)
return alias_cast<void*>(TlsAlloc());
#elif AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS
pthread_key_t* pKey(new pthread_key_t());
pthread_key_create(pKey, NULL);
return alias_cast<void*>(pKey);
#else
#error "Not implemented on this platform"
#endif
}
inline void DestroyTLS(void* pTLSHandle)
{
#if defined(WIN32)
TlsFree(alias_cast<DWORD>(pTLSHandle));
#elif AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS
pthread_key_t* pKey(alias_cast<pthread_key_t*>(pTLSHandle));
pthread_key_delete(*pKey);
#else
#error "Not implemented on this platform"
#endif
}
inline void* GetTLSValue(void* pTLSHandle)
{
#if defined(WIN32)
return TlsGetValue(alias_cast<DWORD>(pTLSHandle));
#elif AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS
return pthread_getspecific(*alias_cast<pthread_key_t*>(pTLSHandle));
#else
#error "Not implemented on this platform"
#endif
}
inline void SetTLSValue(void* pTLSHandle, void* pValue)
{
#if defined(WIN32)
TlsSetValue(alias_cast<DWORD>(pTLSHandle), pValue);
#elif AZ_LEGACY_CRYCOMMON_TRAIT_USE_PTHREADS
pthread_setspecific(*alias_cast<pthread_key_t*>(pTLSHandle), pValue);
#else
#error "Not implemented on this platform"
#endif
}
struct SList
{
typedef SLockFreeSingleLinkedListHeader TListHeader;
typedef SLockFreeSingleLinkedListEntry TListEntry;
SList()
{
CryInitializeSListHead(m_kHeader);
}
void Push(TListEntry& kEntry)
{
CryInterlockedPushEntrySList(m_kHeader, kEntry);
}
TListEntry* Pop()
{
return alias_cast<TListEntry*>(CryInterlockedPopEntrySList(m_kHeader));
}
TListHeader m_kHeader;
};
struct SScopedProfileLabel
{
const char* m_szName;
SScopedProfileLabel(const char* szName)
: m_szName(szName)
{
PushProfileLabel(m_szName);
}
~SScopedProfileLabel()
{
PopProfileLabel(m_szName);
}
};
}
#if DXGL_PROFILING
#define DXGL_SCOPED_PROFILE(_Name) NCryOpenGL::SScopedProfileLabel kDXGLScopedProfileLabel(_Name);
#else
#define DXGL_SCOPED_PROFILE(_Name)
#endif
#endif //__GLPLATFORM__