[dxvk] Added COM helpers

This commit is contained in:
Philip Rebohle 2017-10-11 00:41:56 +02:00
parent 2ee51ea4b2
commit 9b8fda512a
6 changed files with 183 additions and 0 deletions

25
src/util/com/com_guid.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "com_guid.h"
std::ostream& operator << (std::ostream& os, REFIID guid) {
os.width(8);
os << std::hex << guid.Data1 << '-';
os.width(4);
os << std::hex << guid.Data2 << '-';
os.width(4);
os << std::hex << guid.Data3 << '-';
os.width(2);
os << std::hex
<< static_cast<short>(guid.Data4[0])
<< static_cast<short>(guid.Data4[1])
<< '-'
<< static_cast<short>(guid.Data4[2])
<< static_cast<short>(guid.Data4[3])
<< static_cast<short>(guid.Data4[4])
<< static_cast<short>(guid.Data4[5])
<< static_cast<short>(guid.Data4[6])
<< static_cast<short>(guid.Data4[7]);
return os;
}

7
src/util/com/com_guid.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <ostream>
#include "com_include.h"
std::ostream& operator << (std::ostream& os, REFIID guid);

View File

@ -0,0 +1,8 @@
#pragma once
// GCC complains about the COM interfaces
// not having virtual destructors
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

40
src/util/com/com_object.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include <atomic>
#include "com_include.h"
#define COM_QUERY_IFACE(riid, ppvObject, Iface) \
if (riid == __uuidof(Iface)) { \
this->AddRef(); \
*ppvObject = static_cast<Iface*>(this); \
return S_OK; \
}
namespace dxvk {
template<typename... Base>
class ComObject : public Base... {
public:
virtual ~ComObject() { }
ULONG AddRef() final {
return ++m_refCount;
}
ULONG Release() final {
ULONG refCount = --m_refCount;
if (refCount == 0)
delete this;
return refCount;
}
private:
std::atomic<ULONG> m_refCount = { 0ul };
};
}

101
src/util/com/com_pointer.h Normal file
View File

@ -0,0 +1,101 @@
#pragma once
#include "com_include.h"
namespace dxvk {
/**
* \brief COM pointer
*
* Implements automatic reference
* counting for COM objects.
*/
template<typename T>
class Com {
public:
Com() { }
Com(std::nullptr_t) { }
Com(T* object)
: m_ptr(object) {
this->incRef();
}
Com(const Com& other)
: m_ptr(other.m_ptr) {
this->incRef();
}
Com(Com&& other)
: m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
Com& operator = (const Com& other) {
other.incRef();
this->decRef();
m_ptr = other.m_ptr;
return *this;
}
Com& operator = (Com&& other) {
this->decRef();
this->m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
Com& operator = (std::nullptr_t) {
this->decRef();
m_ptr = nullptr;
return *this;
}
~Com() {
this->decRef();
}
T* operator -> () const {
return m_ptr;
}
T** operator & () { return &m_ptr; }
T* const* operator & () const { return &m_ptr; }
bool operator == (std::nullptr_t) const { return m_ptr == nullptr; }
bool operator != (std::nullptr_t) const { return m_ptr != nullptr; }
T* ref() const {
this->incRef();
return m_ptr;
}
T* ptr() const {
return m_ptr;
}
private:
T* m_ptr = nullptr;
void incRef() const {
if (m_ptr != nullptr)
m_ptr->AddRef();
}
void decRef() const {
if (m_ptr != nullptr)
m_ptr->Release();
}
};
template<typename T>
T* ref(T* object) {
if (object != nullptr)
object->AddRef();
return object;
}
}

View File

@ -1,4 +1,6 @@
util_src = files([
'com/com_guid.cpp',
'log/log.cpp',
'log/log_debug.cpp',
])