mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-14 00:48:44 +01:00
150 lines
3.3 KiB
C++
150 lines
3.3 KiB
C++
#include <cmath>
|
|
#include <cstring>
|
|
#include <cstdlib>
|
|
|
|
#include "com_private_data.h"
|
|
|
|
namespace dxvk {
|
|
|
|
ComPrivateDataEntry::ComPrivateDataEntry() { }
|
|
ComPrivateDataEntry::ComPrivateDataEntry(
|
|
REFGUID guid,
|
|
UINT size,
|
|
const void* data)
|
|
: m_guid(guid),
|
|
m_size(size),
|
|
m_data(std::malloc(size)) {
|
|
std::memcpy(m_data, data, size);
|
|
}
|
|
|
|
|
|
ComPrivateDataEntry::ComPrivateDataEntry(
|
|
REFGUID guid,
|
|
const IUnknown* iface)
|
|
: m_guid (guid),
|
|
m_iface (const_cast<IUnknown*>(iface)) {
|
|
m_iface->AddRef();
|
|
}
|
|
|
|
|
|
ComPrivateDataEntry::~ComPrivateDataEntry() {
|
|
this->destroy();
|
|
}
|
|
|
|
|
|
ComPrivateDataEntry::ComPrivateDataEntry(ComPrivateDataEntry&& other)
|
|
: m_guid (other.m_guid),
|
|
m_size (other.m_size),
|
|
m_data (other.m_data),
|
|
m_iface (other.m_iface) {
|
|
other.m_guid = __uuidof(IUnknown);
|
|
other.m_size = 0;
|
|
other.m_data = nullptr;
|
|
other.m_iface = nullptr;
|
|
}
|
|
|
|
|
|
ComPrivateDataEntry& ComPrivateDataEntry::operator = (ComPrivateDataEntry&& other) {
|
|
this->destroy();
|
|
this->m_guid = other.m_guid;
|
|
this->m_size = other.m_size;
|
|
this->m_data = other.m_data;
|
|
this->m_iface = other.m_iface;
|
|
|
|
other.m_guid = __uuidof(IUnknown);
|
|
other.m_size = 0;
|
|
other.m_data = nullptr;
|
|
other.m_iface = nullptr;
|
|
return *this;
|
|
}
|
|
|
|
|
|
HRESULT ComPrivateDataEntry::get(UINT& size, void* data) const {
|
|
if (size != 0 && data == nullptr)
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
const UINT minSize = m_iface != nullptr
|
|
? sizeof(IUnknown*)
|
|
: m_size;
|
|
|
|
const HRESULT result = size < minSize
|
|
? DXGI_ERROR_MORE_DATA
|
|
: S_OK;
|
|
|
|
if (size >= minSize) {
|
|
if (m_iface != nullptr) {
|
|
m_iface->AddRef();
|
|
std::memcpy(data, &m_iface, minSize);
|
|
} else {
|
|
std::memcpy(data, m_data, minSize);
|
|
}
|
|
}
|
|
|
|
size = minSize;
|
|
return result;
|
|
}
|
|
|
|
|
|
void ComPrivateDataEntry::destroy() {
|
|
if (m_data != nullptr)
|
|
std::free(m_data);
|
|
if (m_iface != nullptr)
|
|
m_iface->Release();
|
|
}
|
|
|
|
|
|
HRESULT ComPrivateData::setData(
|
|
REFGUID guid,
|
|
UINT size,
|
|
const void* data) {
|
|
this->insertEntry(ComPrivateDataEntry(guid, size, data));
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT ComPrivateData::setInterface(
|
|
REFGUID guid,
|
|
const IUnknown* iface) {
|
|
this->insertEntry(ComPrivateDataEntry(guid, iface));
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT ComPrivateData::getData(
|
|
REFGUID guid,
|
|
UINT* size,
|
|
void* data) {
|
|
if (size == nullptr)
|
|
return DXGI_ERROR_INVALID_CALL;
|
|
|
|
auto entry = this->findEntry(guid);
|
|
|
|
if (entry == nullptr)
|
|
return DXGI_ERROR_NOT_FOUND;
|
|
|
|
return entry->get(*size, data);
|
|
}
|
|
|
|
|
|
ComPrivateDataEntry* ComPrivateData::findEntry(REFGUID guid) {
|
|
for (ComPrivateDataEntry& e : m_entries) {
|
|
if (e.hasGuid(guid))
|
|
return &e;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
void ComPrivateData::insertEntry(ComPrivateDataEntry&& entry) {
|
|
ComPrivateDataEntry srcEntry = std::move(entry);
|
|
ComPrivateDataEntry* dstEntry = this->findEntry(srcEntry.guid());
|
|
|
|
if (dstEntry != nullptr)
|
|
*dstEntry = std::move(srcEntry);
|
|
else
|
|
m_entries.push_back(std::move(srcEntry));
|
|
}
|
|
|
|
}
|