[dxgi] Implemented some DXGI classes

This commit is contained in:
Philip Rebohle 2017-10-11 03:09:04 +02:00
parent 9b8fda512a
commit bed6d23e7f
15 changed files with 997 additions and 1 deletions

105
src/dxgi/dxgi_adapter.cpp Normal file
View File

@ -0,0 +1,105 @@
#include <cstdlib>
#include <cstring>
#include "dxgi_adapter.h"
#include "dxgi_factory.h"
#include "dxgi_output.h"
namespace dxvk {
DxgiAdapter::DxgiAdapter(
DxgiFactory* factory,
const Rc<DxvkAdapter>& adapter)
: m_factory (factory),
m_adapter (adapter) {
TRACE(this, factory, adapter);
}
DxgiAdapter::~DxgiAdapter() {
TRACE(this);
}
HRESULT DxgiAdapter::QueryInterface(
REFIID riid,
void **ppvObject) {
COM_QUERY_IFACE(riid, ppvObject, IDXGIAdapter);
Logger::warn("DxgiAdapter::QueryInterface: Unknown interface query");
return E_NOINTERFACE;
}
HRESULT DxgiAdapter::GetParent(
REFIID riid,
void **ppParent) {
return m_factory->QueryInterface(riid, ppParent);
}
HRESULT DxgiAdapter::CheckInterfaceSupport(
REFGUID InterfaceName,
LARGE_INTEGER *pUMDVersion) {
Logger::err("DxgiAdapter::CheckInterfaceSupport: No D3D10 support");
return DXGI_ERROR_UNSUPPORTED;
}
HRESULT DxgiAdapter::EnumOutputs(
UINT Output,
IDXGIOutput **ppOutput) {
TRACE(this, Output, ppOutput);
if (ppOutput == nullptr)
return DXGI_ERROR_INVALID_CALL;
int numDisplays = SDL_GetNumVideoDisplays();
if (numDisplays < 0) {
Logger::err("DxgiAdapter::EnumOutputs: Failed to query display count");
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
if (Output >= static_cast<uint32_t>(numDisplays))
return DXGI_ERROR_NOT_FOUND;
*ppOutput = ref(new DxgiOutput(this, Output));
return S_OK;
}
HRESULT DxgiAdapter::GetDesc(DXGI_ADAPTER_DESC* pDesc) {
if (pDesc == nullptr)
return DXGI_ERROR_INVALID_CALL;
const auto deviceProp = m_adapter->deviceProperties();
const auto memoryProp = m_adapter->memoryProperties();
std::memset(pDesc->Description, 0, sizeof(pDesc->Description));
std::mbstowcs(pDesc->Description, deviceProp.deviceName, _countof(pDesc->Description) - 1);
VkDeviceSize deviceMemory = 0;
VkDeviceSize sharedMemory = 0;
for (uint32_t i = 0; i < memoryProp.memoryHeapCount; i++) {
VkMemoryHeap heap = memoryProp.memoryHeaps[i];
if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
deviceMemory += heap.size;
else
sharedMemory += heap.size;
}
pDesc->VendorId = deviceProp.vendorID;
pDesc->DeviceId = deviceProp.deviceID;
pDesc->SubSysId = 0;
pDesc->Revision = 0;
pDesc->DedicatedVideoMemory = deviceMemory;
pDesc->DedicatedSystemMemory = 0;
pDesc->SharedSystemMemory = sharedMemory;
pDesc->AdapterLuid = LUID { 0, 0 }; // TODO implement
return S_OK;
}
}

50
src/dxgi/dxgi_adapter.h Normal file
View File

@ -0,0 +1,50 @@
#pragma once
#include <memory>
#include <vector>
#include <dxvk_adapter.h>
#include "dxgi_object.h"
namespace dxvk {
class DxgiFactory;
class DxgiOutput;
class DxgiAdapter : public DxgiObject<IDXGIAdapter> {
public:
DxgiAdapter(
DxgiFactory* factory,
const Rc<DxvkAdapter>& adapter);
~DxgiAdapter();
HRESULT QueryInterface(
REFIID riid,
void **ppvObject) final;
HRESULT GetParent(
REFIID riid,
void **ppParent) final;
HRESULT CheckInterfaceSupport(
REFGUID InterfaceName,
LARGE_INTEGER *pUMDVersion) final;
HRESULT EnumOutputs(
UINT Output,
IDXGIOutput **ppOutput) final;
HRESULT GetDesc(
DXGI_ADAPTER_DESC *pDesc) final;
private:
DxgiFactory* m_factory;
Rc<DxvkAdapter> m_adapter;
};
}

88
src/dxgi/dxgi_factory.cpp Normal file
View File

@ -0,0 +1,88 @@
#include "dxgi_factory.h"
#include "dxgi_swapchain.h"
namespace dxvk {
DxgiFactory::DxgiFactory()
: m_instance(new DxvkInstance()) {
TRACE(this);
auto adapters = m_instance->enumAdapters();
for (auto a : adapters)
m_adapters.push_back(new DxgiAdapter(this, a));
}
DxgiFactory::~DxgiFactory() {
TRACE(this);
}
HRESULT DxgiFactory::QueryInterface(
REFIID riid,
void** ppvObject) {
COM_QUERY_IFACE(riid, ppvObject, IDXGIFactory);
Logger::warn("DxgiFactory::QueryInterface: Unknown interface query");
return E_NOINTERFACE;
}
HRESULT DxgiFactory::GetParent(
REFIID riid,
void** ppParent) {
Logger::warn("DxgiFactory::GetParent: Unknown interface query");
return E_NOINTERFACE;
}
HRESULT DxgiFactory::CreateSoftwareAdapter(
HMODULE Module,
IDXGIAdapter** ppAdapter) {
Logger::err("DxgiFactory::CreateSoftwareAdapter: Software adapters not supported");
return DXGI_ERROR_UNSUPPORTED;
}
HRESULT DxgiFactory::CreateSwapChain(
IUnknown* pDevice,
DXGI_SWAP_CHAIN_DESC* pDesc,
IDXGISwapChain** ppSwapChain) {
TRACE(this, pDevice, pDesc, ppSwapChain);
return DXGI_ERROR_UNSUPPORTED;
}
HRESULT DxgiFactory::EnumAdapters(
UINT Adapter,
IDXGIAdapter** ppAdapter) {
TRACE(this, Adapter, ppAdapter);
if (ppAdapter == nullptr)
return DXGI_ERROR_INVALID_CALL;
if (Adapter >= m_adapters.size())
return DXGI_ERROR_NOT_FOUND;
*ppAdapter = m_adapters.at(Adapter).ref();
return S_OK;
}
HRESULT DxgiFactory::GetWindowAssociation(HWND *pWindowHandle) {
if (pWindowHandle == nullptr)
return DXGI_ERROR_INVALID_CALL;
*pWindowHandle = m_associatedWindow;
return S_OK;
}
HRESULT DxgiFactory::MakeWindowAssociation(HWND WindowHandle, UINT Flags) {
TRACE(this, WindowHandle, Flags);
Logger::warn("DxgiFactory::MakeWindowAssociation: Ignoring flags");
m_associatedWindow = WindowHandle;
return S_OK;
}
}

55
src/dxgi/dxgi_factory.h Normal file
View File

@ -0,0 +1,55 @@
#pragma once
#include <vector>
#include <dxvk_instance.h>
#include "dxgi_adapter.h"
namespace dxvk {
class DxgiFactory : public DxgiObject<IDXGIFactory> {
public:
DxgiFactory();
~DxgiFactory();
HRESULT QueryInterface(
REFIID riid,
void** ppvObject) final;
HRESULT GetParent(
REFIID riid,
void** ppParent) final;
HRESULT CreateSoftwareAdapter(
HMODULE Module,
IDXGIAdapter** ppAdapter) final;
HRESULT CreateSwapChain(
IUnknown* pDevice,
DXGI_SWAP_CHAIN_DESC* pDesc,
IDXGISwapChain** ppSwapChain) final;
HRESULT EnumAdapters(
UINT Adapter,
IDXGIAdapter** ppAdapter) final;
HRESULT GetWindowAssociation(
HWND *pWindowHandle) final;
HRESULT MakeWindowAssociation(
HWND WindowHandle,
UINT Flags) final;
private:
Rc<DxvkInstance> m_instance;
std::vector<Com<DxgiAdapter>> m_adapters;
HWND m_associatedWindow = nullptr;
};
}

18
src/dxgi/dxgi_include.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#define DLLEXPORT __declspec(dllexport)
#include "../util/com/com_guid.h"
#include "../util/com/com_object.h"
#include "../util/com/com_pointer.h"
#include "../util/log/log.h"
#include "../util/log/log_debug.h"
#include "../util/util_enum.h"
#include "../util/util_error.h"
#include "../util/util_string.h"
#include <dxgi1_2.h>
#include <SDL2/SDL.h>

48
src/dxgi/dxgi_main.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "dxgi_factory.h"
#include "dxgi_include.h"
namespace dxvk {
struct SdlInstance {
SdlInstance() {
TRACE(this);
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE))
Logger::err("Instance::init: Failed to initialize SDL");
}
~SdlInstance() {
TRACE(this);
SDL_Quit();
}
};
SdlInstance sdl;
HRESULT createDxgiFactory(REFIID riid, void **ppFactory) {
TRACE(riid, ppFactory);
if (riid != __uuidof(IDXGIFactory)) {
Logger::err("CreateDXGIFactory: Requested version of IDXGIFactory not supported");
return DXGI_ERROR_UNSUPPORTED;
}
try {
*ppFactory = ref(new DxgiFactory());
return S_OK;
} catch (const DxvkError& err) {
Logger::err(err.message());
return DXGI_ERROR_UNSUPPORTED;
}
}
}
extern "C" {
DLLEXPORT HRESULT __stdcall CreateDXGIFactory1(REFIID riid, void **ppFactory) {
return dxvk::createDxgiFactory(riid, ppFactory);
}
DLLEXPORT HRESULT __stdcall CreateDXGIFactory(REFIID riid, void **ppFactory) {
return dxvk::createDxgiFactory(riid, ppFactory);
}
}

41
src/dxgi/dxgi_object.h Normal file
View File

@ -0,0 +1,41 @@
#pragma once
#include "dxgi_private_data.h"
namespace dxvk {
template<typename Base>
class DxgiObject : public ComObject<Base> {
public:
HRESULT GetPrivateData(
REFGUID Name,
UINT *pDataSize,
void *pData) final {
return m_privateData.getData(
Name, pDataSize, pData);
}
HRESULT SetPrivateData(
REFGUID Name,
UINT DataSize,
const void *pData) final {
return m_privateData.setData(
Name, DataSize, pData);
}
HRESULT SetPrivateDataInterface(
REFGUID Name,
const IUnknown *pUnknown) final {
return m_privateData.setInterface(
Name, pUnknown);
}
private:
DxgiPrivateData m_privateData;
};
}

244
src/dxgi/dxgi_output.cpp Normal file
View File

@ -0,0 +1,244 @@
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <string>
#include "dxgi_adapter.h"
#include "dxgi_output.h"
namespace dxvk {
DxgiOutput::DxgiOutput(
DxgiAdapter* adapter,
UINT display)
: m_adapter (adapter),
m_display (display) {
TRACE(this, adapter);
}
DxgiOutput::~DxgiOutput() {
TRACE(this);
}
HRESULT DxgiOutput::QueryInterface(
REFIID riid,
void **ppvObject) {
COM_QUERY_IFACE(riid, ppvObject, IDXGIOutput);
Logger::warn("DxgiOutput::QueryInterface: Unknown interface query");
return E_NOINTERFACE;
}
HRESULT DxgiOutput::GetParent(
REFIID riid,
void **ppParent) {
return m_adapter->QueryInterface(riid, ppParent);
}
HRESULT DxgiOutput::FindClosestMatchingMode(
const DXGI_MODE_DESC *pModeToMatch,
DXGI_MODE_DESC *pClosestMatch,
IUnknown *pConcernedDevice) {
Logger::err("DxgiOutput::FindClosestMatchingMode: Not implemented");
return E_NOTIMPL;
}
HRESULT DxgiOutput::GetDesc(DXGI_OUTPUT_DESC *pDesc) {
if (pDesc == nullptr)
return DXGI_ERROR_INVALID_CALL;
// Display name, Windows requires wide chars
const char* displayName = SDL_GetDisplayName(m_display);
if (displayName == nullptr) {
Logger::err("DxgiOutput::GetDesc: Failed to get display name");
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
std::memset(pDesc->DeviceName, 0, sizeof(pDesc->DeviceName));
std::mbstowcs(pDesc->DeviceName, displayName, _countof(pDesc->DeviceName) - 1);
// Current desktop rect of the display
SDL_Rect rect;
if (SDL_GetDisplayBounds(m_display, &rect)) {
Logger::err("DxgiOutput::GetDesc: Failed to get display bounds");
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
pDesc->DesktopCoordinates.left = rect.x;
pDesc->DesktopCoordinates.top = rect.y;
pDesc->DesktopCoordinates.right = rect.x + rect.w;
pDesc->DesktopCoordinates.bottom = rect.y + rect.h;
// We don't have any info for these
pDesc->AttachedToDesktop = 1;
pDesc->Rotation = DXGI_MODE_ROTATION_UNSPECIFIED;
pDesc->Monitor = nullptr;
return S_OK;
}
HRESULT DxgiOutput::GetDisplayModeList(
DXGI_FORMAT EnumFormat,
UINT Flags,
UINT *pNumModes,
DXGI_MODE_DESC *pDesc) {
TRACE(this, EnumFormat, Flags, pNumModes, pDesc);
if (pNumModes == nullptr)
return DXGI_ERROR_INVALID_CALL;
// In order to check whether a display mode is 'centered' or
// 'streched' in DXGI terms, we compare its size to the desktop
// 'mode. If they are the same, we consider the mode to be
// 'centered', which most games will prefer over 'streched'.
SDL_DisplayMode desktopMode;
if (SDL_GetDesktopDisplayMode(m_display, &desktopMode)) {
Logger::err("DxgiOutput::GetDisplayModeList: Failed to list display modes");
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
// Create a list of suitable display modes. Because of the way DXGI
// swapchains are handled by DXVK, we can ignore the format constraints
// here and just pick whatever modes SDL returns for the current display.
std::vector<DXGI_MODE_DESC> modes;
int numDisplayModes = SDL_GetNumDisplayModes(m_display);
if (numDisplayModes < 0) {
Logger::err("DxgiOutput::GetDisplayModeList: Failed to list display modes");
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
for (int i = 0; i < numDisplayModes; i++) {
SDL_DisplayMode currMode;
if (SDL_GetDisplayMode(m_display, i, &currMode)) {
Logger::err("DxgiOutput::GetDisplayModeList: Failed to list display modes");
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
// We don't want duplicates, so we'll filter out modes
// with matching resolution and refresh rate.
bool hasMode = false;
for (int j = 0; j < i && !hasMode; j++) {
SDL_DisplayMode testMode;
if (SDL_GetDisplayMode(m_display, j, &testMode)) {
Logger::err("DxgiOutput::GetDisplayModeList: Failed to list display modes");
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
}
hasMode = testMode.w == currMode.w
&& testMode.h == currMode.h
&& testMode.refresh_rate == currMode.refresh_rate;
}
// Convert the SDL display mode to a DXGI display mode info
// structure and filter out any unwanted modes based on the
// supplied flags.
if (!hasMode) {
bool isNativeMode = (currMode.w == desktopMode.w)
&& (currMode.h == desktopMode.h);
if (isNativeMode || (Flags & DXGI_ENUM_MODES_SCALING)) {
DXGI_MODE_DESC mode;
mode.Width = currMode.w;
mode.Height = currMode.h;
mode.RefreshRate.Numerator = currMode.refresh_rate;
mode.RefreshRate.Denominator = 1;
mode.Format = EnumFormat;
mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
mode.Scaling = isNativeMode
? DXGI_MODE_SCALING_CENTERED
: DXGI_MODE_SCALING_STRETCHED;
modes.push_back(mode);
}
}
}
// Copy list of display modes to the application-provided
// destination buffer. The buffer may not be appropriately
// sized by the time this is called.
if (pDesc != nullptr) {
for (uint32_t i = 0; i < modes.size() && i < *pNumModes; i++)
pDesc[i] = modes.at(i);
}
// If the buffer is too small, we shall ask the application
// to query the display mode list again by returning the
// appropriate DXGI error code.
if ((pDesc == nullptr) || (modes.size() <= *pNumModes)) {
*pNumModes = modes.size();
return S_OK;
} else {
return DXGI_ERROR_MORE_DATA;
}
}
HRESULT DxgiOutput::GetDisplaySurfaceData(IDXGISurface *pDestination) {
Logger::err("DxgiOutput::GetDisplaySurfaceData: Not implemented");
return E_NOTIMPL;
}
HRESULT DxgiOutput::GetFrameStatistics(DXGI_FRAME_STATISTICS *pStats) {
Logger::err("DxgiOutput::GetFrameStatistics: Not implemented");
return E_NOTIMPL;
}
HRESULT DxgiOutput::GetGammaControl(DXGI_GAMMA_CONTROL *pArray) {
Logger::err("DxgiOutput::GetGammaControl: Not implemented");
return E_NOTIMPL;
}
HRESULT DxgiOutput::GetGammaControlCapabilities(DXGI_GAMMA_CONTROL_CAPABILITIES *pGammaCaps) {
Logger::err("DxgiOutput::GetGammaControlCapabilities: Not implemented");
return E_NOTIMPL;
}
void DxgiOutput::ReleaseOwnership() {
Logger::warn("DxgiOutput::ReleaseOwnership: Stub");
}
HRESULT DxgiOutput::SetDisplaySurface(IDXGISurface *pScanoutSurface) {
Logger::err("DxgiOutput::SetDisplaySurface: Not implemented");
return E_NOTIMPL;
}
HRESULT DxgiOutput::SetGammaControl(const DXGI_GAMMA_CONTROL *pArray) {
Logger::err("DxgiOutput::SetGammaControl: Not implemented");
return E_NOTIMPL;
}
HRESULT DxgiOutput::TakeOwnership(
IUnknown *pDevice,
BOOL Exclusive) {
Logger::warn("DxgiOutput::TakeOwnership: Stub");
return S_OK;
}
HRESULT DxgiOutput::WaitForVBlank() {
Logger::warn("DxgiOutput::WaitForVBlank: Stub");
return S_OK;
}
}

74
src/dxgi/dxgi_output.h Normal file
View File

@ -0,0 +1,74 @@
#pragma once
#include "dxgi_object.h"
namespace dxvk {
class DxgiAdapter;
class DxgiOutput : public DxgiObject<IDXGIOutput> {
public:
DxgiOutput(
DxgiAdapter* adapter,
UINT display);
~DxgiOutput();
HRESULT QueryInterface(
REFIID riid,
void **ppvObject) final;
HRESULT GetParent(
REFIID riid,
void **ppParent) final;
HRESULT FindClosestMatchingMode(
const DXGI_MODE_DESC *pModeToMatch,
DXGI_MODE_DESC *pClosestMatch,
IUnknown *pConcernedDevice) final;
HRESULT GetDesc(
DXGI_OUTPUT_DESC *pDesc) final;
HRESULT GetDisplayModeList(
DXGI_FORMAT EnumFormat,
UINT Flags,
UINT *pNumModes,
DXGI_MODE_DESC *pDesc) final;
HRESULT GetDisplaySurfaceData(
IDXGISurface *pDestination) final;
HRESULT GetFrameStatistics(
DXGI_FRAME_STATISTICS *pStats) final;
HRESULT GetGammaControl(
DXGI_GAMMA_CONTROL *pArray) final;
HRESULT GetGammaControlCapabilities(
DXGI_GAMMA_CONTROL_CAPABILITIES *pGammaCaps) final;
void ReleaseOwnership() final;
HRESULT SetDisplaySurface(
IDXGISurface *pScanoutSurface) final;
HRESULT SetGammaControl(
const DXGI_GAMMA_CONTROL *pArray) final;
HRESULT TakeOwnership(
IUnknown *pDevice,
BOOL Exclusive) final;
HRESULT WaitForVBlank() final;
private:
DxgiAdapter* m_adapter;
UINT m_display;
};
}

View File

@ -0,0 +1,149 @@
#include <cmath>
#include <cstring>
#include <cstdlib>
#include "dxgi_private_data.h"
namespace dxvk {
DxgiPrivateDataEntry::DxgiPrivateDataEntry() { }
DxgiPrivateDataEntry::DxgiPrivateDataEntry(
REFGUID guid,
UINT size,
const void* data)
: m_guid(guid),
m_size(size),
m_data(std::malloc(size)) {
std::memcpy(m_data, data, size);
}
DxgiPrivateDataEntry::DxgiPrivateDataEntry(
REFGUID guid,
const IUnknown* iface)
: m_guid (guid),
m_iface (const_cast<IUnknown*>(iface)) {
m_iface->AddRef();
}
DxgiPrivateDataEntry::~DxgiPrivateDataEntry() {
this->destroy();
}
DxgiPrivateDataEntry::DxgiPrivateDataEntry(DxgiPrivateDataEntry&& 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;
}
DxgiPrivateDataEntry& DxgiPrivateDataEntry::operator = (DxgiPrivateDataEntry&& 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 DxgiPrivateDataEntry::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 DxgiPrivateDataEntry::destroy() {
if (m_data != nullptr)
std::free(m_data);
if (m_iface != nullptr)
m_iface->Release();
}
HRESULT DxgiPrivateData::setData(
REFGUID guid,
UINT size,
const void* data) {
this->insertEntry(DxgiPrivateDataEntry(guid, size, data));
return S_OK;
}
HRESULT DxgiPrivateData::setInterface(
REFGUID guid,
const IUnknown* iface) {
this->insertEntry(DxgiPrivateDataEntry(guid, iface));
return S_OK;
}
HRESULT DxgiPrivateData::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);
}
DxgiPrivateDataEntry* DxgiPrivateData::findEntry(REFGUID guid) {
for (DxgiPrivateDataEntry& e : m_entries) {
if (e.hasGuid(guid))
return &e;
}
return nullptr;
}
void DxgiPrivateData::insertEntry(DxgiPrivateDataEntry&& entry) {
DxgiPrivateDataEntry srcEntry = std::move(entry);
DxgiPrivateDataEntry* dstEntry = this->findEntry(srcEntry.guid());
if (dstEntry != nullptr)
*dstEntry = std::move(srcEntry);
else
m_entries.push_back(std::move(srcEntry));
}
}

View File

@ -0,0 +1,105 @@
#pragma once
#include <vector>
#include "dxgi_include.h"
namespace dxvk {
/**
* \brief Data entry for private storage
* Stores a single private storage item.
*/
class DxgiPrivateDataEntry {
public:
DxgiPrivateDataEntry();
DxgiPrivateDataEntry(
REFGUID guid,
UINT size,
const void* data);
DxgiPrivateDataEntry(
REFGUID guid,
const IUnknown* iface);
~DxgiPrivateDataEntry();
DxgiPrivateDataEntry (DxgiPrivateDataEntry&& other);
DxgiPrivateDataEntry& operator = (DxgiPrivateDataEntry&& other);
/**
* \brief The entry's GUID
* \returns The GUID
*/
REFGUID guid() const {
return m_guid;
}
/**
* \brief Checks whether the GUID matches another one
*
* GUIDs are used to identify private data entries.
* \param [in] guid The GUID to compare to
* \returns \c true if this entry holds the same GUID
*/
bool hasGuid(REFGUID guid) const {
return m_guid == guid;
}
/**
* \brief Retrieves stored data
*
* \param [in,out] size Destination buffer size
* \param [in] data Appliaction-provided buffer
* \returns \c S_OK on success, or \c DXGI_ERROR_MORE_DATA
* if the destination buffer is too small
*/
HRESULT get(UINT& size, void* data) const;
private:
GUID m_guid = __uuidof(IUnknown);
UINT m_size = 0;
void* m_data = nullptr;
IUnknown* m_iface = nullptr;
void destroy();
};
/**
* \brief Private storage for DXGI objects
*
* Provides storage for application-defined
* byte arrays or COM interfaces that can be
* retrieved using GUIDs.
*/
class DxgiPrivateData {
public:
HRESULT setData(
REFGUID guid,
UINT size,
const void* data);
HRESULT setInterface(
REFGUID guid,
const IUnknown* iface);
HRESULT getData(
REFGUID guid,
UINT* size,
void* data);
private:
std::vector<DxgiPrivateDataEntry> m_entries;
DxgiPrivateDataEntry* findEntry(REFGUID guid);
void insertEntry(DxgiPrivateDataEntry&& entry);
};
}

View File

View File

17
src/dxgi/meson.build Normal file
View File

@ -0,0 +1,17 @@
dxgi_src = [
'dxgi_adapter.cpp',
'dxgi_factory.cpp',
'dxgi_main.cpp',
'dxgi_output.cpp',
'dxgi_private_data.cpp',
'dxgi_swapchain.cpp',
]
dxgi_dll = shared_library('dxgi', dxgi_src,
link_with : [ util_lib ],
dependencies : [ dxvk_dep ],
include_directories : dxvk_include_path)
dxgi_dep = declare_dependency(
link_with : [ dxgi_dll ],
include_directories : [ dxvk_include_path, include_directories('.') ])

View File

@ -1,2 +1,4 @@
subdir('util')
subdir('dxvk')
subdir('dxvk')
subdir('dxgi')
subdir('d3d11')