mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-30 01:25:51 +00:00
Qt: Replace QWindow for display with QWidget base
Not as elegant, but it solves the input focus issue.
This commit is contained in:
parent
db1070a683
commit
2480624cbe
|
@ -26,12 +26,12 @@ add_executable(duckstation-qt
|
||||||
mainwindow.cpp
|
mainwindow.cpp
|
||||||
mainwindow.h
|
mainwindow.h
|
||||||
mainwindow.ui
|
mainwindow.ui
|
||||||
opengldisplaywindow.cpp
|
opengldisplaywidget.cpp
|
||||||
opengldisplaywindow.h
|
opengldisplaywidget.h
|
||||||
portsettingswidget.cpp
|
portsettingswidget.cpp
|
||||||
portsettingswidget.h
|
portsettingswidget.h
|
||||||
qtdisplaywindow.cpp
|
qtdisplaywidget.cpp
|
||||||
qtdisplaywindow.h
|
qtdisplaywidget.h
|
||||||
qthostinterface.cpp
|
qthostinterface.cpp
|
||||||
qthostinterface.h
|
qthostinterface.h
|
||||||
qtsettingsinterface.cpp
|
qtsettingsinterface.cpp
|
||||||
|
@ -47,8 +47,8 @@ target_link_libraries(duckstation-qt PRIVATE frontend-common core common imgui g
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_sources(duckstation-qt PRIVATE
|
target_sources(duckstation-qt PRIVATE
|
||||||
d3d11displaywindow.cpp
|
d3d11displaywidget.cpp
|
||||||
d3d11displaywindow.h
|
d3d11displaywidget.h
|
||||||
)
|
)
|
||||||
target_link_libraries(duckstation PRIVATE d3d11.lib dxgi.lib)
|
target_link_libraries(duckstation PRIVATE d3d11.lib dxgi.lib)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "d3d11displaywindow.h"
|
#include "d3d11displaywidget.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/d3d11/shader_compiler.h"
|
#include "common/d3d11/shader_compiler.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
@ -8,20 +8,20 @@
|
||||||
#include <dxgi1_5.h>
|
#include <dxgi1_5.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_impl_dx11.h>
|
#include <imgui_impl_dx11.h>
|
||||||
Log_SetChannel(D3D11DisplayWindow);
|
Log_SetChannel(D3D11DisplayWidget);
|
||||||
|
|
||||||
class D3D11DisplayWindowTexture : public HostDisplayTexture
|
class D3D11DisplayWidgetTexture : public HostDisplayTexture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||||
|
|
||||||
D3D11DisplayWindowTexture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv, u32 width,
|
D3D11DisplayWidgetTexture(ComPtr<ID3D11Texture2D> texture, ComPtr<ID3D11ShaderResourceView> srv, u32 width,
|
||||||
u32 height, bool dynamic)
|
u32 height, bool dynamic)
|
||||||
: m_texture(std::move(texture)), m_srv(std::move(srv)), m_width(width), m_height(height), m_dynamic(dynamic)
|
: m_texture(std::move(texture)), m_srv(std::move(srv)), m_width(width), m_height(height), m_dynamic(dynamic)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~D3D11DisplayWindowTexture() override = default;
|
~D3D11DisplayWidgetTexture() override = default;
|
||||||
|
|
||||||
void* GetHandle() const override { return m_srv.Get(); }
|
void* GetHandle() const override { return m_srv.Get(); }
|
||||||
u32 GetWidth() const override { return m_width; }
|
u32 GetWidth() const override { return m_width; }
|
||||||
|
@ -31,7 +31,7 @@ public:
|
||||||
ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); }
|
ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); }
|
||||||
bool IsDynamic() const { return m_dynamic; }
|
bool IsDynamic() const { return m_dynamic; }
|
||||||
|
|
||||||
static std::unique_ptr<D3D11DisplayWindowTexture> Create(ID3D11Device* device, u32 width, u32 height,
|
static std::unique_ptr<D3D11DisplayWidgetTexture> Create(ID3D11Device* device, u32 width, u32 height,
|
||||||
const void* data, u32 data_stride, bool dynamic)
|
const void* data, u32 data_stride, bool dynamic)
|
||||||
{
|
{
|
||||||
const CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, D3D11_BIND_SHADER_RESOURCE,
|
const CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, D3D11_BIND_SHADER_RESOURCE,
|
||||||
|
@ -50,7 +50,7 @@ public:
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return std::make_unique<D3D11DisplayWindowTexture>(std::move(texture), std::move(srv), width, height, dynamic);
|
return std::make_unique<D3D11DisplayWidgetTexture>(std::move(texture), std::move(srv), width, height, dynamic);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -61,76 +61,58 @@ private:
|
||||||
bool m_dynamic;
|
bool m_dynamic;
|
||||||
};
|
};
|
||||||
|
|
||||||
D3D11DisplayWindow::D3D11DisplayWindow(QtHostInterface* host_interface, QWindow* parent)
|
D3D11DisplayWidget::D3D11DisplayWidget(QtHostInterface* host_interface, QWidget* parent)
|
||||||
: QtDisplayWindow(host_interface, parent)
|
: QtDisplayWidget(host_interface, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D11DisplayWindow::~D3D11DisplayWindow() = default;
|
D3D11DisplayWidget::~D3D11DisplayWidget() = default;
|
||||||
|
|
||||||
HostDisplay* D3D11DisplayWindow::getHostDisplayInterface()
|
HostDisplay* D3D11DisplayWidget::getHostDisplayInterface()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
HostDisplay::RenderAPI D3D11DisplayWindow::GetRenderAPI() const
|
HostDisplay::RenderAPI D3D11DisplayWidget::GetRenderAPI() const
|
||||||
{
|
{
|
||||||
return HostDisplay::RenderAPI::D3D11;
|
return HostDisplay::RenderAPI::D3D11;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* D3D11DisplayWindow::GetRenderDevice() const
|
void* D3D11DisplayWidget::GetRenderDevice() const
|
||||||
{
|
{
|
||||||
return m_device.Get();
|
return m_device.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* D3D11DisplayWindow::GetRenderContext() const
|
void* D3D11DisplayWidget::GetRenderContext() const
|
||||||
{
|
{
|
||||||
return m_context.Get();
|
return m_context.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* D3D11DisplayWindow::GetRenderWindow() const
|
void* D3D11DisplayWidget::GetRenderWindow() const
|
||||||
{
|
{
|
||||||
return const_cast<QWindow*>(static_cast<const QWindow*>(this));
|
return const_cast<QWidget*>(static_cast<const QWidget*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11DisplayWindow::ChangeRenderWindow(void* new_window)
|
void D3D11DisplayWidget::ChangeRenderWindow(void* new_window)
|
||||||
{
|
{
|
||||||
Panic("Not supported");
|
Panic("Not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11DisplayWindow::WindowResized(s32 new_window_width, s32 new_window_height)
|
std::unique_ptr<HostDisplayTexture> D3D11DisplayWidget::CreateTexture(u32 width, u32 height, const void* initial_data,
|
||||||
|
u32 initial_data_stride, bool dynamic)
|
||||||
{
|
{
|
||||||
QtDisplayWindow::WindowResized(new_window_width, new_window_height);
|
return D3D11DisplayWidgetTexture::Create(m_device.Get(), width, height, initial_data, initial_data_stride, dynamic);
|
||||||
HostDisplay::WindowResized(new_window_width, new_window_height);
|
|
||||||
|
|
||||||
if (!m_swap_chain)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_swap_chain_rtv.Reset();
|
|
||||||
|
|
||||||
HRESULT hr = m_swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN,
|
|
||||||
m_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
|
||||||
if (FAILED(hr))
|
|
||||||
Log_ErrorPrintf("ResizeBuffers() failed: 0x%08X", hr);
|
|
||||||
|
|
||||||
if (!createSwapChainRTV())
|
|
||||||
Panic("Failed to recreate swap chain RTV after resize");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<HostDisplayTexture> D3D11DisplayWindow::CreateTexture(u32 width, u32 height, const void* data,
|
void D3D11DisplayWidget::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height,
|
||||||
u32 data_stride, bool dynamic)
|
const void* texture_data, u32 texture_data_stride)
|
||||||
{
|
{
|
||||||
return D3D11DisplayWindowTexture::Create(m_device.Get(), width, height, data, data_stride, dynamic);
|
D3D11DisplayWidgetTexture* d3d11_texture = static_cast<D3D11DisplayWidgetTexture*>(texture);
|
||||||
}
|
|
||||||
|
|
||||||
void D3D11DisplayWindow::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height,
|
|
||||||
const void* data, u32 data_stride)
|
|
||||||
{
|
|
||||||
D3D11DisplayWindowTexture* d3d11_texture = static_cast<D3D11DisplayWindowTexture*>(texture);
|
|
||||||
if (!d3d11_texture->IsDynamic())
|
if (!d3d11_texture->IsDynamic())
|
||||||
{
|
{
|
||||||
const CD3D11_BOX dst_box(x, y, 0, x + width, y + height, 1);
|
const CD3D11_BOX dst_box(x, y, 0, x + width, y + height, 1);
|
||||||
m_context->UpdateSubresource(d3d11_texture->GetD3DTexture(), 0, &dst_box, data, data_stride, data_stride * height);
|
m_context->UpdateSubresource(d3d11_texture->GetD3DTexture(), 0, &dst_box, texture_data, texture_data_stride,
|
||||||
|
texture_data_stride * height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -140,17 +122,17 @@ void D3D11DisplayWindow::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y
|
||||||
Panic("Failed to map dynamic host display texture");
|
Panic("Failed to map dynamic host display texture");
|
||||||
|
|
||||||
char* dst_ptr = static_cast<char*>(sr.pData) + (y * sr.RowPitch) + (x * sizeof(u32));
|
char* dst_ptr = static_cast<char*>(sr.pData) + (y * sr.RowPitch) + (x * sizeof(u32));
|
||||||
const char* src_ptr = static_cast<const char*>(data);
|
const char* src_ptr = static_cast<const char*>(texture_data);
|
||||||
if (sr.RowPitch == data_stride)
|
if (sr.RowPitch == texture_data_stride)
|
||||||
{
|
{
|
||||||
std::memcpy(dst_ptr, src_ptr, data_stride * height);
|
std::memcpy(dst_ptr, src_ptr, texture_data_stride * height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (u32 row = 0; row < height; row++)
|
for (u32 row = 0; row < height; row++)
|
||||||
{
|
{
|
||||||
std::memcpy(dst_ptr, src_ptr, width * sizeof(u32));
|
std::memcpy(dst_ptr, src_ptr, width * sizeof(u32));
|
||||||
src_ptr += data_stride;
|
src_ptr += texture_data_stride;
|
||||||
dst_ptr += sr.RowPitch;
|
dst_ptr += sr.RowPitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,44 +141,24 @@ void D3D11DisplayWindow::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11DisplayWindow::SetVSync(bool enabled)
|
void D3D11DisplayWidget::SetVSync(bool enabled)
|
||||||
{
|
{
|
||||||
m_vsync = enabled;
|
m_vsync = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11DisplayWindow::hasDeviceContext() const
|
bool D3D11DisplayWidget::hasDeviceContext() const
|
||||||
{
|
{
|
||||||
return static_cast<bool>(m_device);
|
return static_cast<bool>(m_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_device)
|
bool D3D11DisplayWidget::createDeviceContext(QThread* worker_thread, bool debug_device)
|
||||||
{
|
{
|
||||||
ComPtr<IDXGIFactory> dxgi_factory;
|
|
||||||
HRESULT hr = CreateDXGIFactory(IID_PPV_ARGS(dxgi_factory.GetAddressOf()));
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
Log_ErrorPrintf("Failed to create DXGI factory: 0x%08X", hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_allow_tearing_supported = false;
|
|
||||||
ComPtr<IDXGIFactory5> dxgi_factory5;
|
|
||||||
hr = dxgi_factory.As(&dxgi_factory5);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
BOOL allow_tearing_supported = false;
|
|
||||||
hr = dxgi_factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing_supported,
|
|
||||||
sizeof(allow_tearing_supported));
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
m_allow_tearing_supported = (allow_tearing_supported == TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT create_flags = 0;
|
UINT create_flags = 0;
|
||||||
if (debug_device)
|
if (debug_device)
|
||||||
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
|
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||||
|
|
||||||
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0, D3D11_SDK_VERSION,
|
HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0,
|
||||||
m_device.GetAddressOf(), nullptr, m_context.GetAddressOf());
|
D3D11_SDK_VERSION, m_device.GetAddressOf(), nullptr, m_context.GetAddressOf());
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
@ -204,40 +166,6 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DXGI_SWAP_CHAIN_DESC swap_chain_desc = {};
|
|
||||||
swap_chain_desc.BufferDesc.Width = m_window_width;
|
|
||||||
swap_chain_desc.BufferDesc.Height = m_window_height;
|
|
||||||
swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
||||||
swap_chain_desc.SampleDesc.Count = 1;
|
|
||||||
swap_chain_desc.BufferCount = 3;
|
|
||||||
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
||||||
swap_chain_desc.OutputWindow = reinterpret_cast<HWND>(winId());
|
|
||||||
swap_chain_desc.Windowed = TRUE;
|
|
||||||
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
|
||||||
|
|
||||||
if (m_allow_tearing_supported)
|
|
||||||
swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
|
||||||
|
|
||||||
hr = dxgi_factory->CreateSwapChain(m_device.Get(), &swap_chain_desc, m_swap_chain.GetAddressOf());
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
Log_WarningPrintf("Failed to create a flip-discard swap chain, trying discard.");
|
|
||||||
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
|
||||||
swap_chain_desc.Flags = 0;
|
|
||||||
m_allow_tearing_supported = false;
|
|
||||||
|
|
||||||
hr = dxgi_factory->CreateSwapChain(m_device.Get(), &swap_chain_desc, m_swap_chain.GetAddressOf());
|
|
||||||
if (FAILED(hr))
|
|
||||||
{
|
|
||||||
Log_ErrorPrintf("CreateSwapChain failed: 0x%08X", hr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = dxgi_factory->MakeWindowAssociation(swap_chain_desc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES);
|
|
||||||
if (FAILED(hr))
|
|
||||||
Log_WarningPrintf("MakeWindowAssociation() to disable ALT+ENTER failed");
|
|
||||||
|
|
||||||
if (debug_device)
|
if (debug_device)
|
||||||
{
|
{
|
||||||
ComPtr<ID3D11InfoQueue> info;
|
ComPtr<ID3D11InfoQueue> info;
|
||||||
|
@ -249,7 +177,46 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!QtDisplayWindow::createDeviceContext(worker_thread, debug_device))
|
// we need the specific factory for the device, otherwise MakeWindowAssociation() is flaky.
|
||||||
|
ComPtr<IDXGIDevice> dxgi_device;
|
||||||
|
ComPtr<IDXGIAdapter> dxgi_adapter;
|
||||||
|
if (FAILED(m_device.As(&dxgi_device)) || FAILED(dxgi_device->GetParent(IID_PPV_ARGS(dxgi_adapter.GetAddressOf()))) ||
|
||||||
|
FAILED(dxgi_adapter->GetParent(IID_PPV_ARGS(m_dxgi_factory.GetAddressOf()))))
|
||||||
|
{
|
||||||
|
Log_WarningPrint("Failed to get parent adapter/device/factory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DXGI_ADAPTER_DESC adapter_desc;
|
||||||
|
if (SUCCEEDED(dxgi_adapter->GetDesc(&adapter_desc)))
|
||||||
|
{
|
||||||
|
char adapter_name_buffer[128];
|
||||||
|
const int name_length =
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, adapter_desc.Description, static_cast<int>(std::wcslen(adapter_desc.Description)),
|
||||||
|
adapter_name_buffer, countof(adapter_name_buffer), 0, nullptr);
|
||||||
|
if (name_length >= 0)
|
||||||
|
{
|
||||||
|
adapter_name_buffer[name_length] = 0;
|
||||||
|
Log_InfoPrintf("D3D Adapter: %s", adapter_name_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_allow_tearing_supported = false;
|
||||||
|
ComPtr<IDXGIFactory5> dxgi_factory5;
|
||||||
|
hr = m_dxgi_factory.As(&dxgi_factory5);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
BOOL allow_tearing_supported = false;
|
||||||
|
hr = dxgi_factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allow_tearing_supported,
|
||||||
|
sizeof(allow_tearing_supported));
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
m_allow_tearing_supported = (allow_tearing_supported == TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!createSwapChain(reinterpret_cast<HWND>(winId())))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!QtDisplayWidget::createDeviceContext(worker_thread, debug_device))
|
||||||
{
|
{
|
||||||
m_swap_chain.Reset();
|
m_swap_chain.Reset();
|
||||||
m_context.Reset();
|
m_context.Reset();
|
||||||
|
@ -259,26 +226,86 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11DisplayWindow::initializeDeviceContext(bool debug_device)
|
bool D3D11DisplayWidget::initializeDeviceContext(bool debug_device)
|
||||||
{
|
{
|
||||||
if (!createSwapChainRTV())
|
if (!createSwapChainRTV())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!QtDisplayWindow::initializeDeviceContext(debug_device))
|
if (!QtDisplayWidget::initializeDeviceContext(debug_device))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11DisplayWindow::destroyDeviceContext()
|
void D3D11DisplayWidget::destroyDeviceContext()
|
||||||
{
|
{
|
||||||
QtDisplayWindow::destroyDeviceContext();
|
QtDisplayWidget::destroyDeviceContext();
|
||||||
m_swap_chain.Reset();
|
m_swap_chain.Reset();
|
||||||
m_context.Reset();
|
m_context.Reset();
|
||||||
m_device.Reset();
|
m_device.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11DisplayWindow::createSwapChainRTV()
|
bool D3D11DisplayWidget::createSwapChain(HWND hwnd)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
DXGI_SWAP_CHAIN_DESC swap_chain_desc = {};
|
||||||
|
swap_chain_desc.BufferDesc.Width = m_window_width;
|
||||||
|
swap_chain_desc.BufferDesc.Height = m_window_height;
|
||||||
|
swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
swap_chain_desc.SampleDesc.Count = 1;
|
||||||
|
swap_chain_desc.BufferCount = 3;
|
||||||
|
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
swap_chain_desc.OutputWindow = hwnd;
|
||||||
|
swap_chain_desc.Windowed = TRUE;
|
||||||
|
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
|
|
||||||
|
if (m_allow_tearing_supported)
|
||||||
|
swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||||
|
|
||||||
|
hr = m_dxgi_factory->CreateSwapChain(m_device.Get(), &swap_chain_desc, m_swap_chain.GetAddressOf());
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Failed to create a flip-discard swap chain, trying discard.");
|
||||||
|
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
|
swap_chain_desc.Flags = 0;
|
||||||
|
m_allow_tearing_supported = false;
|
||||||
|
|
||||||
|
hr = m_dxgi_factory->CreateSwapChain(m_device.Get(), &swap_chain_desc, m_swap_chain.GetAddressOf());
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
Log_ErrorPrintf("CreateSwapChain failed: 0x%08X", hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = m_dxgi_factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
|
||||||
|
if (FAILED(hr))
|
||||||
|
Log_WarningPrintf("MakeWindowAssociation() to disable ALT+ENTER failed");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D3D11DisplayWidget::windowResized(s32 new_window_width, s32 new_window_height)
|
||||||
|
{
|
||||||
|
QtDisplayWidget::windowResized(new_window_width, new_window_height);
|
||||||
|
HostDisplay::WindowResized(new_window_width, new_window_height);
|
||||||
|
|
||||||
|
if (!m_swap_chain)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_swap_chain_rtv.Reset();
|
||||||
|
|
||||||
|
HRESULT hr = m_swap_chain->ResizeBuffers(0, new_window_width, new_window_height, DXGI_FORMAT_UNKNOWN,
|
||||||
|
m_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
||||||
|
if (FAILED(hr))
|
||||||
|
Log_ErrorPrintf("ResizeBuffers() failed: 0x%08X", hr);
|
||||||
|
|
||||||
|
if (!createSwapChainRTV())
|
||||||
|
Panic("Failed to recreate swap chain RTV after resize");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool D3D11DisplayWidget::createSwapChainRTV()
|
||||||
{
|
{
|
||||||
ComPtr<ID3D11Texture2D> backbuffer;
|
ComPtr<ID3D11Texture2D> backbuffer;
|
||||||
HRESULT hr = m_swap_chain->GetBuffer(0, IID_PPV_ARGS(backbuffer.GetAddressOf()));
|
HRESULT hr = m_swap_chain->GetBuffer(0, IID_PPV_ARGS(backbuffer.GetAddressOf()));
|
||||||
|
@ -303,7 +330,7 @@ bool D3D11DisplayWindow::createSwapChainRTV()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11DisplayWindow::createDeviceResources()
|
bool D3D11DisplayWidget::createDeviceResources()
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -349,9 +376,9 @@ bool D3D11DisplayWindow::createDeviceResources()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11DisplayWindow::destroyDeviceResources()
|
void D3D11DisplayWidget::destroyDeviceResources()
|
||||||
{
|
{
|
||||||
QtDisplayWindow::destroyDeviceResources();
|
QtDisplayWidget::destroyDeviceResources();
|
||||||
|
|
||||||
m_display_uniform_buffer.Release();
|
m_display_uniform_buffer.Release();
|
||||||
m_swap_chain_rtv.Reset();
|
m_swap_chain_rtv.Reset();
|
||||||
|
@ -364,9 +391,9 @@ void D3D11DisplayWindow::destroyDeviceResources()
|
||||||
m_display_rasterizer_state.Reset();
|
m_display_rasterizer_state.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11DisplayWindow::createImGuiContext()
|
bool D3D11DisplayWidget::createImGuiContext()
|
||||||
{
|
{
|
||||||
if (!QtDisplayWindow::createImGuiContext())
|
if (!QtDisplayWidget::createImGuiContext())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!ImGui_ImplDX11_Init(m_device.Get(), m_context.Get()))
|
if (!ImGui_ImplDX11_Init(m_device.Get(), m_context.Get()))
|
||||||
|
@ -377,13 +404,13 @@ bool D3D11DisplayWindow::createImGuiContext()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11DisplayWindow::destroyImGuiContext()
|
void D3D11DisplayWidget::destroyImGuiContext()
|
||||||
{
|
{
|
||||||
ImGui_ImplDX11_Shutdown();
|
ImGui_ImplDX11_Shutdown();
|
||||||
QtDisplayWindow::destroyImGuiContext();
|
QtDisplayWidget::destroyImGuiContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11DisplayWindow::Render()
|
void D3D11DisplayWidget::Render()
|
||||||
{
|
{
|
||||||
static constexpr std::array<float, 4> clear_color = {};
|
static constexpr std::array<float, 4> clear_color = {};
|
||||||
m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color.data());
|
m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color.data());
|
||||||
|
@ -403,7 +430,7 @@ void D3D11DisplayWindow::Render()
|
||||||
ImGui_ImplDX11_NewFrame();
|
ImGui_ImplDX11_NewFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void D3D11DisplayWindow::renderDisplay()
|
void D3D11DisplayWidget::renderDisplay()
|
||||||
{
|
{
|
||||||
if (!m_display_texture_handle)
|
if (!m_display_texture_handle)
|
||||||
return;
|
return;
|
|
@ -1,14 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common/windows_headers.h"
|
|
||||||
#include "common/d3d11/stream_buffer.h"
|
#include "common/d3d11/stream_buffer.h"
|
||||||
#include "common/d3d11/texture.h"
|
#include "common/d3d11/texture.h"
|
||||||
|
#include "common/windows_headers.h"
|
||||||
#include "core/host_display.h"
|
#include "core/host_display.h"
|
||||||
#include "qtdisplaywindow.h"
|
#include "qtdisplaywidget.h"
|
||||||
#include <d3d11.h>
|
#include <d3d11.h>
|
||||||
|
#include <dxgi.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
|
|
||||||
class D3D11DisplayWindow final : public QtDisplayWindow, private HostDisplay
|
class D3D11DisplayWidget final : public QtDisplayWidget, private HostDisplay
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -16,8 +17,8 @@ public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||||
|
|
||||||
D3D11DisplayWindow(QtHostInterface* host_interface, QWindow* parent);
|
D3D11DisplayWidget(QtHostInterface* host_interface, QWidget* parent);
|
||||||
~D3D11DisplayWindow();
|
~D3D11DisplayWidget();
|
||||||
|
|
||||||
HostDisplay* getHostDisplayInterface() override;
|
HostDisplay* getHostDisplayInterface() override;
|
||||||
|
|
||||||
|
@ -32,12 +33,12 @@ public:
|
||||||
void* GetRenderWindow() const override;
|
void* GetRenderWindow() const override;
|
||||||
|
|
||||||
void ChangeRenderWindow(void* new_window) override;
|
void ChangeRenderWindow(void* new_window) override;
|
||||||
void WindowResized(s32 new_window_width, s32 new_window_height) override;
|
void windowResized(s32 new_window_width, s32 new_window_height) override;
|
||||||
|
|
||||||
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* data, u32 data_stride,
|
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* initial_data,
|
||||||
bool dynamic) override;
|
u32 initial_data_stride, bool dynamic) override;
|
||||||
void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data,
|
void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* texture_data,
|
||||||
u32 data_stride) override;
|
u32 texture_data_stride) override;
|
||||||
|
|
||||||
void SetVSync(bool enabled) override;
|
void SetVSync(bool enabled) override;
|
||||||
|
|
||||||
|
@ -51,10 +52,13 @@ private:
|
||||||
bool createDeviceResources() override;
|
bool createDeviceResources() override;
|
||||||
void destroyDeviceResources() override;
|
void destroyDeviceResources() override;
|
||||||
|
|
||||||
|
bool createSwapChain(HWND hwnd);
|
||||||
bool createSwapChainRTV();
|
bool createSwapChainRTV();
|
||||||
|
|
||||||
void renderDisplay();
|
void renderDisplay();
|
||||||
|
|
||||||
|
ComPtr<IDXGIFactory> m_dxgi_factory;
|
||||||
|
|
||||||
ComPtr<ID3D11Device> m_device;
|
ComPtr<ID3D11Device> m_device;
|
||||||
ComPtr<ID3D11DeviceContext> m_context;
|
ComPtr<ID3D11DeviceContext> m_context;
|
||||||
ComPtr<IDXGISwapChain> m_swap_chain;
|
ComPtr<IDXGISwapChain> m_swap_chain;
|
|
@ -37,16 +37,16 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="audiosettingswidget.cpp" />
|
<ClCompile Include="audiosettingswidget.cpp" />
|
||||||
<ClCompile Include="consolesettingswidget.cpp" />
|
<ClCompile Include="consolesettingswidget.cpp" />
|
||||||
<ClCompile Include="d3d11displaywindow.cpp" />
|
<ClCompile Include="d3d11displaywidget.cpp" />
|
||||||
<ClCompile Include="gpusettingswidget.cpp" />
|
<ClCompile Include="gpusettingswidget.cpp" />
|
||||||
<ClCompile Include="hotkeysettingswidget.cpp" />
|
<ClCompile Include="hotkeysettingswidget.cpp" />
|
||||||
<ClCompile Include="inputbindingwidgets.cpp" />
|
<ClCompile Include="inputbindingwidgets.cpp" />
|
||||||
<ClCompile Include="qtdisplaywindow.cpp" />
|
<ClCompile Include="qtdisplaywidget.cpp" />
|
||||||
<ClCompile Include="gamelistsettingswidget.cpp" />
|
<ClCompile Include="gamelistsettingswidget.cpp" />
|
||||||
<ClCompile Include="gamelistwidget.cpp" />
|
<ClCompile Include="gamelistwidget.cpp" />
|
||||||
<ClCompile Include="main.cpp" />
|
<ClCompile Include="main.cpp" />
|
||||||
<ClCompile Include="mainwindow.cpp" />
|
<ClCompile Include="mainwindow.cpp" />
|
||||||
<ClCompile Include="opengldisplaywindow.cpp" />
|
<ClCompile Include="opengldisplaywidget.cpp" />
|
||||||
<ClCompile Include="portsettingswidget.cpp" />
|
<ClCompile Include="portsettingswidget.cpp" />
|
||||||
<ClCompile Include="qthostinterface.cpp" />
|
<ClCompile Include="qthostinterface.cpp" />
|
||||||
<ClCompile Include="qtsettingsinterface.cpp" />
|
<ClCompile Include="qtsettingsinterface.cpp" />
|
||||||
|
@ -56,17 +56,17 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtMoc Include="audiosettingswidget.h" />
|
<QtMoc Include="audiosettingswidget.h" />
|
||||||
<QtMoc Include="portsettingswidget.h" />
|
<QtMoc Include="portsettingswidget.h" />
|
||||||
<QtMoc Include="qtdisplaywindow.h" />
|
<QtMoc Include="qtdisplaywidget.h" />
|
||||||
<QtMoc Include="gpusettingswidget.h" />
|
<QtMoc Include="gpusettingswidget.h" />
|
||||||
<QtMoc Include="hotkeysettingswidget.h" />
|
<QtMoc Include="hotkeysettingswidget.h" />
|
||||||
<QtMoc Include="inputbindingwidgets.h" />
|
<QtMoc Include="inputbindingwidgets.h" />
|
||||||
<QtMoc Include="d3d11displaywindow.h" />
|
<QtMoc Include="d3d11displaywidget.h" />
|
||||||
<ClInclude Include="settingwidgetbinder.h" />
|
<ClInclude Include="settingwidgetbinder.h" />
|
||||||
<QtMoc Include="consolesettingswidget.h" />
|
<QtMoc Include="consolesettingswidget.h" />
|
||||||
<QtMoc Include="gamelistsettingswidget.h" />
|
<QtMoc Include="gamelistsettingswidget.h" />
|
||||||
<QtMoc Include="gamelistwidget.h" />
|
<QtMoc Include="gamelistwidget.h" />
|
||||||
<QtMoc Include="mainwindow.h" />
|
<QtMoc Include="mainwindow.h" />
|
||||||
<QtMoc Include="opengldisplaywindow.h" />
|
<QtMoc Include="opengldisplaywidget.h" />
|
||||||
<QtMoc Include="qthostinterface.h" />
|
<QtMoc Include="qthostinterface.h" />
|
||||||
<ClInclude Include="qtsettingsinterface.h" />
|
<ClInclude Include="qtsettingsinterface.h" />
|
||||||
<ClInclude Include="qtutils.h" />
|
<ClInclude Include="qtutils.h" />
|
||||||
|
@ -117,16 +117,16 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="$(IntDir)moc_audiosettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_audiosettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_consolesettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_consolesettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_d3d11displaywindow.cpp" />
|
<ClCompile Include="$(IntDir)moc_d3d11displaywidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_gamelistsettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gamelistsettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_gamelistwidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gamelistwidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_hotkeysettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_hotkeysettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_inputbindingwidgets.cpp" />
|
<ClCompile Include="$(IntDir)moc_inputbindingwidgets.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_mainwindow.cpp" />
|
<ClCompile Include="$(IntDir)moc_mainwindow.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_opengldisplaywindow.cpp" />
|
<ClCompile Include="$(IntDir)moc_opengldisplaywidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_portsettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_portsettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_qtdisplaywindow.cpp" />
|
<ClCompile Include="$(IntDir)moc_qtdisplaywidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_qthostinterface.cpp" />
|
<ClCompile Include="$(IntDir)moc_qthostinterface.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_settingsdialog.cpp" />
|
<ClCompile Include="$(IntDir)moc_settingsdialog.cpp" />
|
||||||
<ClCompile Include="$(IntDir)qrc_icons.cpp" />
|
<ClCompile Include="$(IntDir)qrc_icons.cpp" />
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
<ClCompile Include="gamelistwidget.cpp" />
|
<ClCompile Include="gamelistwidget.cpp" />
|
||||||
<ClCompile Include="settingsdialog.cpp" />
|
<ClCompile Include="settingsdialog.cpp" />
|
||||||
<ClCompile Include="consolesettingswidget.cpp" />
|
<ClCompile Include="consolesettingswidget.cpp" />
|
||||||
<ClCompile Include="opengldisplaywindow.cpp" />
|
|
||||||
<ClCompile Include="qthostinterface.cpp" />
|
<ClCompile Include="qthostinterface.cpp" />
|
||||||
<ClCompile Include="gamelistsettingswidget.cpp" />
|
<ClCompile Include="gamelistsettingswidget.cpp" />
|
||||||
<ClCompile Include="qtsettingsinterface.cpp" />
|
<ClCompile Include="qtsettingsinterface.cpp" />
|
||||||
|
@ -15,24 +14,25 @@
|
||||||
<ClCompile Include="$(IntDir)moc_gamelistsettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gamelistsettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_gamelistwidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gamelistwidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_mainwindow.cpp" />
|
<ClCompile Include="$(IntDir)moc_mainwindow.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_opengldisplaywindow.cpp" />
|
|
||||||
<ClCompile Include="$(IntDir)moc_qthostinterface.cpp" />
|
<ClCompile Include="$(IntDir)moc_qthostinterface.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_settingsdialog.cpp" />
|
<ClCompile Include="$(IntDir)moc_settingsdialog.cpp" />
|
||||||
<ClCompile Include="$(IntDir)qrc_icons.cpp" />
|
<ClCompile Include="$(IntDir)qrc_icons.cpp" />
|
||||||
<ClCompile Include="portsettingswidget.cpp" />
|
<ClCompile Include="portsettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_portsettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_portsettingswidget.cpp" />
|
||||||
<ClCompile Include="qtdisplaywindow.cpp" />
|
|
||||||
<ClCompile Include="$(IntDir)moc_qtdisplaywindow.cpp" />
|
|
||||||
<ClCompile Include="gpusettingswidget.cpp" />
|
<ClCompile Include="gpusettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
||||||
<ClCompile Include="inputbindingwidgets.cpp" />
|
<ClCompile Include="inputbindingwidgets.cpp" />
|
||||||
<ClCompile Include="hotkeysettingswidget.cpp" />
|
<ClCompile Include="hotkeysettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_hotkeysettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_hotkeysettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_inputbindingwidgets.cpp" />
|
<ClCompile Include="$(IntDir)moc_inputbindingwidgets.cpp" />
|
||||||
<ClCompile Include="d3d11displaywindow.cpp" />
|
|
||||||
<ClCompile Include="$(IntDir)moc_d3d11displaywindow.cpp" />
|
|
||||||
<ClCompile Include="audiosettingswidget.cpp" />
|
<ClCompile Include="audiosettingswidget.cpp" />
|
||||||
<ClCompile Include="$(IntDir)moc_audiosettingswidget.cpp" />
|
<ClCompile Include="$(IntDir)moc_audiosettingswidget.cpp" />
|
||||||
|
<ClCompile Include="opengldisplaywidget.cpp" />
|
||||||
|
<ClCompile Include="d3d11displaywidget.cpp" />
|
||||||
|
<ClCompile Include="$(IntDir)moc_d3d11displaywidget.cpp" />
|
||||||
|
<ClCompile Include="$(IntDir)moc_opengldisplaywidget.cpp" />
|
||||||
|
<ClCompile Include="$(IntDir)moc_qtdisplaywidget.cpp" />
|
||||||
|
<ClCompile Include="qtdisplaywidget.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="qtsettingsinterface.h" />
|
<ClInclude Include="qtsettingsinterface.h" />
|
||||||
|
@ -52,16 +52,16 @@
|
||||||
<QtMoc Include="gamelistsettingswidget.h" />
|
<QtMoc Include="gamelistsettingswidget.h" />
|
||||||
<QtMoc Include="gamelistwidget.h" />
|
<QtMoc Include="gamelistwidget.h" />
|
||||||
<QtMoc Include="mainwindow.h" />
|
<QtMoc Include="mainwindow.h" />
|
||||||
<QtMoc Include="opengldisplaywindow.h" />
|
|
||||||
<QtMoc Include="qthostinterface.h" />
|
<QtMoc Include="qthostinterface.h" />
|
||||||
<QtMoc Include="settingsdialog.h" />
|
<QtMoc Include="settingsdialog.h" />
|
||||||
<QtMoc Include="portsettingswidget.h" />
|
<QtMoc Include="portsettingswidget.h" />
|
||||||
<QtMoc Include="qtdisplaywindow.h" />
|
|
||||||
<QtMoc Include="gpusettingswidget.h" />
|
<QtMoc Include="gpusettingswidget.h" />
|
||||||
<QtMoc Include="hotkeysettingswidget.h" />
|
<QtMoc Include="hotkeysettingswidget.h" />
|
||||||
<QtMoc Include="inputbindingwidgets.h" />
|
<QtMoc Include="inputbindingwidgets.h" />
|
||||||
<QtMoc Include="d3d11displaywindow.h" />
|
|
||||||
<QtMoc Include="audiosettingswidget.h" />
|
<QtMoc Include="audiosettingswidget.h" />
|
||||||
|
<QtMoc Include="opengldisplaywidget.h" />
|
||||||
|
<QtMoc Include="d3d11displaywidget.h" />
|
||||||
|
<QtMoc Include="qtdisplaywidget.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtUi Include="consolesettingswidget.ui" />
|
<QtUi Include="consolesettingswidget.ui" />
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "core/system.h"
|
#include "core/system.h"
|
||||||
#include "gamelistsettingswidget.h"
|
#include "gamelistsettingswidget.h"
|
||||||
#include "gamelistwidget.h"
|
#include "gamelistwidget.h"
|
||||||
#include "qtdisplaywindow.h"
|
#include "qtdisplaywidget.h"
|
||||||
#include "qthostinterface.h"
|
#include "qthostinterface.h"
|
||||||
#include "qtsettingsinterface.h"
|
#include "qtsettingsinterface.h"
|
||||||
#include "settingsdialog.h"
|
#include "settingsdialog.h"
|
||||||
|
@ -57,10 +57,7 @@ void MainWindow::createDisplayWindow(QThread* worker_thread, bool use_debug_devi
|
||||||
{
|
{
|
||||||
DebugAssert(!m_display_widget);
|
DebugAssert(!m_display_widget);
|
||||||
|
|
||||||
QtDisplayWindow* display_window = m_host_interface->createDisplayWindow();
|
m_display_widget = m_host_interface->createDisplayWidget();
|
||||||
DebugAssert(display_window);
|
|
||||||
|
|
||||||
m_display_widget = QWidget::createWindowContainer(display_window, m_ui.mainContainer);
|
|
||||||
DebugAssert(m_display_widget);
|
DebugAssert(m_display_widget);
|
||||||
|
|
||||||
m_display_widget->setFocusPolicy(Qt::StrongFocus);
|
m_display_widget->setFocusPolicy(Qt::StrongFocus);
|
||||||
|
@ -70,7 +67,7 @@ void MainWindow::createDisplayWindow(QThread* worker_thread, bool use_debug_devi
|
||||||
switchToEmulationView();
|
switchToEmulationView();
|
||||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||||
|
|
||||||
display_window->createDeviceContext(worker_thread, use_debug_device);
|
m_display_widget->createDeviceContext(worker_thread, use_debug_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::destroyDisplayWindow()
|
void MainWindow::destroyDisplayWindow()
|
||||||
|
|
|
@ -12,6 +12,7 @@ class QThread;
|
||||||
|
|
||||||
class GameListWidget;
|
class GameListWidget;
|
||||||
class QtHostInterface;
|
class QtHostInterface;
|
||||||
|
class QtDisplayWidget;
|
||||||
|
|
||||||
struct GameListEntry;
|
struct GameListEntry;
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ private:
|
||||||
QtHostInterface* m_host_interface = nullptr;
|
QtHostInterface* m_host_interface = nullptr;
|
||||||
|
|
||||||
GameListWidget* m_game_list_widget = nullptr;
|
GameListWidget* m_game_list_widget = nullptr;
|
||||||
QWidget* m_display_widget = nullptr;
|
QtDisplayWidget* m_display_widget = nullptr;
|
||||||
|
|
||||||
QLabel* m_status_speed_widget = nullptr;
|
QLabel* m_status_speed_widget = nullptr;
|
||||||
QLabel* m_status_fps_widget = nullptr;
|
QLabel* m_status_fps_widget = nullptr;
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
#include "opengldisplaywindow.h"
|
#include "opengldisplaywidget.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "qthostinterface.h"
|
#include "qthostinterface.h"
|
||||||
#include <QtGui/QKeyEvent>
|
#include <QtGui/QKeyEvent>
|
||||||
|
#include <QtGui/QWindow>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <imgui_impl_opengl3.h>
|
#include <imgui_impl_opengl3.h>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
Log_SetChannel(OpenGLDisplayWindow);
|
Log_SetChannel(OpenGLDisplayWidget);
|
||||||
|
|
||||||
static thread_local QOpenGLContext* s_thread_gl_context;
|
static thread_local QOpenGLContext* s_thread_gl_context;
|
||||||
|
|
||||||
|
@ -56,11 +57,11 @@ static void SetSwapInterval(QWindow* window, QOpenGLContext* context, int interv
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenGLHostDisplayTexture : public HostDisplayTexture
|
class OpenGLDisplayWidgetTexture : public HostDisplayTexture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OpenGLHostDisplayTexture(GLuint id, u32 width, u32 height) : m_id(id), m_width(width), m_height(height) {}
|
OpenGLDisplayWidgetTexture(GLuint id, u32 width, u32 height) : m_id(id), m_width(width), m_height(height) {}
|
||||||
~OpenGLHostDisplayTexture() override { glDeleteTextures(1, &m_id); }
|
~OpenGLDisplayWidgetTexture() override { glDeleteTextures(1, &m_id); }
|
||||||
|
|
||||||
void* GetHandle() const override { return reinterpret_cast<void*>(static_cast<uintptr_t>(m_id)); }
|
void* GetHandle() const override { return reinterpret_cast<void*>(static_cast<uintptr_t>(m_id)); }
|
||||||
u32 GetWidth() const override { return m_width; }
|
u32 GetWidth() const override { return m_width; }
|
||||||
|
@ -68,7 +69,7 @@ public:
|
||||||
|
|
||||||
GLuint GetGLID() const { return m_id; }
|
GLuint GetGLID() const { return m_id; }
|
||||||
|
|
||||||
static std::unique_ptr<OpenGLHostDisplayTexture> Create(u32 width, u32 height, const void* initial_data,
|
static std::unique_ptr<OpenGLDisplayWidgetTexture> Create(u32 width, u32 height, const void* initial_data,
|
||||||
u32 initial_data_stride)
|
u32 initial_data_stride)
|
||||||
{
|
{
|
||||||
GLuint id;
|
GLuint id;
|
||||||
|
@ -87,7 +88,7 @@ public:
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
return std::make_unique<OpenGLHostDisplayTexture>(id, width, height);
|
return std::make_unique<OpenGLDisplayWidgetTexture>(id, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -96,82 +97,84 @@ private:
|
||||||
u32 m_height;
|
u32 m_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
OpenGLDisplayWindow::OpenGLDisplayWindow(QtHostInterface* host_interface, QWindow* parent)
|
OpenGLDisplayWidget::OpenGLDisplayWidget(QtHostInterface* host_interface, QWidget* parent)
|
||||||
: QtDisplayWindow(host_interface, parent)
|
: QtDisplayWidget(host_interface, parent)
|
||||||
{
|
{
|
||||||
setSurfaceType(QWindow::OpenGLSurface);
|
QWindow* native_window = windowHandle();
|
||||||
|
Assert(native_window);
|
||||||
|
native_window->setSurfaceType(QWindow::OpenGLSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLDisplayWindow::~OpenGLDisplayWindow() = default;
|
OpenGLDisplayWidget::~OpenGLDisplayWidget() = default;
|
||||||
|
|
||||||
HostDisplay* OpenGLDisplayWindow::getHostDisplayInterface()
|
HostDisplay* OpenGLDisplayWidget::getHostDisplayInterface()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
HostDisplay::RenderAPI OpenGLDisplayWindow::GetRenderAPI() const
|
HostDisplay::RenderAPI OpenGLDisplayWidget::GetRenderAPI() const
|
||||||
{
|
{
|
||||||
return m_gl_context->isOpenGLES() ? HostDisplay::RenderAPI::OpenGLES : HostDisplay::RenderAPI::OpenGL;
|
return m_gl_context->isOpenGLES() ? HostDisplay::RenderAPI::OpenGLES : HostDisplay::RenderAPI::OpenGL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* OpenGLDisplayWindow::GetRenderDevice() const
|
void* OpenGLDisplayWidget::GetRenderDevice() const
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* OpenGLDisplayWindow::GetRenderContext() const
|
void* OpenGLDisplayWidget::GetRenderContext() const
|
||||||
{
|
{
|
||||||
return m_gl_context.get();
|
return m_gl_context.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* OpenGLDisplayWindow::GetRenderWindow() const
|
void* OpenGLDisplayWidget::GetRenderWindow() const
|
||||||
{
|
{
|
||||||
return const_cast<QWindow*>(static_cast<const QWindow*>(this));
|
return const_cast<QWidget*>(static_cast<const QWidget*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayWindow::ChangeRenderWindow(void* new_window)
|
void OpenGLDisplayWidget::ChangeRenderWindow(void* new_window)
|
||||||
{
|
{
|
||||||
Panic("Not implemented");
|
Panic("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayWindow::WindowResized(s32 new_window_width, s32 new_window_height)
|
void OpenGLDisplayWidget::windowResized(s32 new_window_width, s32 new_window_height)
|
||||||
{
|
{
|
||||||
QtDisplayWindow::WindowResized(new_window_width, new_window_height);
|
QtDisplayWidget::windowResized(new_window_width, new_window_height);
|
||||||
HostDisplay::WindowResized(new_window_width, new_window_height);
|
HostDisplay::WindowResized(new_window_width, new_window_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<HostDisplayTexture> OpenGLDisplayWindow::CreateTexture(u32 width, u32 height, const void* data,
|
std::unique_ptr<HostDisplayTexture> OpenGLDisplayWidget::CreateTexture(u32 width, u32 height, const void* initial_data,
|
||||||
u32 data_stride, bool dynamic)
|
u32 initial_data_stride, bool dynamic)
|
||||||
{
|
{
|
||||||
return OpenGLHostDisplayTexture::Create(width, height, data, data_stride);
|
return OpenGLDisplayWidgetTexture::Create(width, height, initial_data, initial_data_stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayWindow::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height,
|
void OpenGLDisplayWidget::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height,
|
||||||
const void* data, u32 data_stride)
|
const void* texture_data, u32 texture_data_stride)
|
||||||
{
|
{
|
||||||
OpenGLHostDisplayTexture* tex = static_cast<OpenGLHostDisplayTexture*>(texture);
|
OpenGLDisplayWidgetTexture* tex = static_cast<OpenGLDisplayWidgetTexture*>(texture);
|
||||||
Assert(data_stride == (width * sizeof(u32)));
|
Assert(texture_data_stride == (width * sizeof(u32)));
|
||||||
|
|
||||||
GLint old_texture_binding = 0;
|
GLint old_texture_binding = 0;
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture_binding);
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture_binding);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex->GetGLID());
|
glBindTexture(GL_TEXTURE_2D, tex->GetGLID());
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, old_texture_binding);
|
glBindTexture(GL_TEXTURE_2D, old_texture_binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayWindow::SetVSync(bool enabled)
|
void OpenGLDisplayWidget::SetVSync(bool enabled)
|
||||||
{
|
{
|
||||||
// Window framebuffer has to be bound to call SetSwapInterval.
|
// Window framebuffer has to be bound to call SetSwapInterval.
|
||||||
GLint current_fbo = 0;
|
GLint current_fbo = 0;
|
||||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo);
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo);
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
SetSwapInterval(this, m_gl_context.get(), enabled ? 1 : 0);
|
SetSwapInterval(windowHandle(), m_gl_context.get(), enabled ? 1 : 0);
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_fbo);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_fbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* OpenGLDisplayWindow::GetGLSLVersionString() const
|
const char* OpenGLDisplayWidget::GetGLSLVersionString() const
|
||||||
{
|
{
|
||||||
if (m_gl_context->isOpenGLES())
|
if (m_gl_context->isOpenGLES())
|
||||||
{
|
{
|
||||||
|
@ -189,7 +192,7 @@ const char* OpenGLDisplayWindow::GetGLSLVersionString() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OpenGLDisplayWindow::GetGLSLVersionHeader() const
|
std::string OpenGLDisplayWidget::GetGLSLVersionHeader() const
|
||||||
{
|
{
|
||||||
std::string header = GetGLSLVersionString();
|
std::string header = GetGLSLVersionString();
|
||||||
header += "\n\n";
|
header += "\n\n";
|
||||||
|
@ -222,12 +225,12 @@ static void APIENTRY GLDebugCallback(GLenum source, GLenum type, GLuint id, GLen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLDisplayWindow::hasDeviceContext() const
|
bool OpenGLDisplayWidget::hasDeviceContext() const
|
||||||
{
|
{
|
||||||
return static_cast<bool>(m_gl_context);
|
return static_cast<bool>(m_gl_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_device)
|
bool OpenGLDisplayWidget::createDeviceContext(QThread* worker_thread, bool debug_device)
|
||||||
{
|
{
|
||||||
m_gl_context = std::make_unique<QOpenGLContext>();
|
m_gl_context = std::make_unique<QOpenGLContext>();
|
||||||
|
|
||||||
|
@ -236,7 +239,7 @@ bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug
|
||||||
{{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}, {3, 2}, {3, 1}, {3, 0}}};
|
{{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}, {3, 2}, {3, 1}, {3, 0}}};
|
||||||
static constexpr std::array<std::tuple<int, int>, 4> es_versions_to_try = {{{3, 2}, {3, 1}, {3, 0}}};
|
static constexpr std::array<std::tuple<int, int>, 4> es_versions_to_try = {{{3, 2}, {3, 1}, {3, 0}}};
|
||||||
|
|
||||||
QSurfaceFormat surface_format = requestedFormat();
|
QSurfaceFormat surface_format; // = requestedFormat();
|
||||||
surface_format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
|
surface_format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
|
||||||
surface_format.setSwapInterval(0);
|
surface_format.setSwapInterval(0);
|
||||||
surface_format.setRenderableType(QSurfaceFormat::OpenGL);
|
surface_format.setRenderableType(QSurfaceFormat::OpenGL);
|
||||||
|
@ -280,14 +283,14 @@ bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug
|
||||||
Log_InfoPrintf("Got a %s %d.%d context", (m_gl_context->isOpenGLES() ? "OpenGL ES" : "desktop OpenGL"),
|
Log_InfoPrintf("Got a %s %d.%d context", (m_gl_context->isOpenGLES() ? "OpenGL ES" : "desktop OpenGL"),
|
||||||
surface_format.majorVersion(), surface_format.minorVersion());
|
surface_format.majorVersion(), surface_format.minorVersion());
|
||||||
|
|
||||||
if (!m_gl_context->makeCurrent(this))
|
if (!m_gl_context->makeCurrent(windowHandle()))
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Failed to make GL context current on UI thread");
|
Log_ErrorPrintf("Failed to make GL context current on UI thread");
|
||||||
m_gl_context.reset();
|
m_gl_context.reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!QtDisplayWindow::createDeviceContext(worker_thread, debug_device))
|
if (!QtDisplayWidget::createDeviceContext(worker_thread, debug_device))
|
||||||
{
|
{
|
||||||
m_gl_context->doneCurrent();
|
m_gl_context->doneCurrent();
|
||||||
m_gl_context.reset();
|
m_gl_context.reset();
|
||||||
|
@ -299,9 +302,9 @@ bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLDisplayWindow::initializeDeviceContext(bool debug_device)
|
bool OpenGLDisplayWidget::initializeDeviceContext(bool debug_device)
|
||||||
{
|
{
|
||||||
if (!m_gl_context->makeCurrent(this))
|
if (!m_gl_context->makeCurrent(windowHandle()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
s_thread_gl_context = m_gl_context.get();
|
s_thread_gl_context = m_gl_context.get();
|
||||||
|
@ -324,7 +327,7 @@ bool OpenGLDisplayWindow::initializeDeviceContext(bool debug_device)
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!QtDisplayWindow::initializeDeviceContext(debug_device))
|
if (!QtDisplayWidget::initializeDeviceContext(debug_device))
|
||||||
{
|
{
|
||||||
s_thread_gl_context = nullptr;
|
s_thread_gl_context = nullptr;
|
||||||
m_gl_context->doneCurrent();
|
m_gl_context->doneCurrent();
|
||||||
|
@ -334,20 +337,20 @@ bool OpenGLDisplayWindow::initializeDeviceContext(bool debug_device)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayWindow::destroyDeviceContext()
|
void OpenGLDisplayWidget::destroyDeviceContext()
|
||||||
{
|
{
|
||||||
Assert(m_gl_context && s_thread_gl_context == m_gl_context.get());
|
Assert(m_gl_context && s_thread_gl_context == m_gl_context.get());
|
||||||
|
|
||||||
QtDisplayWindow::destroyDeviceContext();
|
QtDisplayWidget::destroyDeviceContext();
|
||||||
|
|
||||||
s_thread_gl_context = nullptr;
|
s_thread_gl_context = nullptr;
|
||||||
m_gl_context->doneCurrent();
|
m_gl_context->doneCurrent();
|
||||||
m_gl_context.reset();
|
m_gl_context.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLDisplayWindow::createImGuiContext()
|
bool OpenGLDisplayWidget::createImGuiContext()
|
||||||
{
|
{
|
||||||
if (!QtDisplayWindow::createImGuiContext())
|
if (!QtDisplayWidget::createImGuiContext())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!ImGui_ImplOpenGL3_Init(GetGLSLVersionString()))
|
if (!ImGui_ImplOpenGL3_Init(GetGLSLVersionString()))
|
||||||
|
@ -358,14 +361,14 @@ bool OpenGLDisplayWindow::createImGuiContext()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayWindow::destroyImGuiContext()
|
void OpenGLDisplayWidget::destroyImGuiContext()
|
||||||
{
|
{
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
|
|
||||||
QtDisplayWindow::destroyImGuiContext();
|
QtDisplayWidget::destroyImGuiContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLDisplayWindow::createDeviceResources()
|
bool OpenGLDisplayWidget::createDeviceResources()
|
||||||
{
|
{
|
||||||
static constexpr char fullscreen_quad_vertex_shader[] = R"(
|
static constexpr char fullscreen_quad_vertex_shader[] = R"(
|
||||||
uniform vec4 u_src_rect;
|
uniform vec4 u_src_rect;
|
||||||
|
@ -425,9 +428,9 @@ void main()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayWindow::destroyDeviceResources()
|
void OpenGLDisplayWidget::destroyDeviceResources()
|
||||||
{
|
{
|
||||||
QtDisplayWindow::destroyDeviceResources();
|
QtDisplayWidget::destroyDeviceResources();
|
||||||
|
|
||||||
if (m_display_vao != 0)
|
if (m_display_vao != 0)
|
||||||
glDeleteVertexArrays(1, &m_display_vao);
|
glDeleteVertexArrays(1, &m_display_vao);
|
||||||
|
@ -439,7 +442,7 @@ void OpenGLDisplayWindow::destroyDeviceResources()
|
||||||
m_display_program.Destroy();
|
m_display_program.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayWindow::Render()
|
void OpenGLDisplayWidget::Render()
|
||||||
{
|
{
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
@ -451,8 +454,9 @@ void OpenGLDisplayWindow::Render()
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||||
|
|
||||||
m_gl_context->makeCurrent(this);
|
QWindow* window_handle = windowHandle();
|
||||||
m_gl_context->swapBuffers(this);
|
m_gl_context->makeCurrent(window_handle);
|
||||||
|
m_gl_context->swapBuffers(window_handle);
|
||||||
|
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
|
@ -460,7 +464,7 @@ void OpenGLDisplayWindow::Render()
|
||||||
GL::Program::ResetLastProgram();
|
GL::Program::ResetLastProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayWindow::renderDisplay()
|
void OpenGLDisplayWidget::renderDisplay()
|
||||||
{
|
{
|
||||||
if (!m_display_texture_handle)
|
if (!m_display_texture_handle)
|
||||||
return;
|
return;
|
|
@ -11,19 +11,19 @@
|
||||||
#include "common/gl/program.h"
|
#include "common/gl/program.h"
|
||||||
#include "common/gl/texture.h"
|
#include "common/gl/texture.h"
|
||||||
#include "core/host_display.h"
|
#include "core/host_display.h"
|
||||||
#include "qtdisplaywindow.h"
|
#include "qtdisplaywidget.h"
|
||||||
#include <QtGui/QOpenGLContext>
|
#include <QtGui/QOpenGLContext>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class QtHostInterface;
|
class QtHostInterface;
|
||||||
|
|
||||||
class OpenGLDisplayWindow final : public QtDisplayWindow, public HostDisplay
|
class OpenGLDisplayWidget final : public QtDisplayWidget, public HostDisplay
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenGLDisplayWindow(QtHostInterface* host_interface, QWindow* parent);
|
OpenGLDisplayWidget(QtHostInterface* host_interface, QWidget* parent);
|
||||||
~OpenGLDisplayWindow();
|
~OpenGLDisplayWidget();
|
||||||
|
|
||||||
HostDisplay* getHostDisplayInterface() override;
|
HostDisplay* getHostDisplayInterface() override;
|
||||||
|
|
||||||
|
@ -38,12 +38,12 @@ public:
|
||||||
void* GetRenderWindow() const override;
|
void* GetRenderWindow() const override;
|
||||||
|
|
||||||
void ChangeRenderWindow(void* new_window) override;
|
void ChangeRenderWindow(void* new_window) override;
|
||||||
void WindowResized(s32 new_window_width, s32 new_window_height) override;
|
void windowResized(s32 new_window_width, s32 new_window_height) override;
|
||||||
|
|
||||||
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* data, u32 data_stride,
|
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* initial_data,
|
||||||
bool dynamic) override;
|
u32 initial_data_stride, bool dynamic) override;
|
||||||
void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data,
|
void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* texture_data,
|
||||||
u32 data_stride) override;
|
u32 texture_data_stride) override;
|
||||||
|
|
||||||
void SetVSync(bool enabled) override;
|
void SetVSync(bool enabled) override;
|
||||||
|
|
145
src/duckstation-qt/qtdisplaywidget.cpp
Normal file
145
src/duckstation-qt/qtdisplaywidget.cpp
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
#include "qtdisplaywidget.h"
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "qthostinterface.h"
|
||||||
|
#include "qtutils.h"
|
||||||
|
#include <QtGui/QGuiApplication>
|
||||||
|
#include <QtGui/QKeyEvent>
|
||||||
|
#include <QtGui/QScreen>
|
||||||
|
#include <QtGui/QWindow>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
QtDisplayWidget::QtDisplayWidget(QtHostInterface* host_interface, QWidget* parent)
|
||||||
|
: QWidget(parent), m_host_interface(host_interface)
|
||||||
|
{
|
||||||
|
// We want a native window for both D3D and OpenGL.
|
||||||
|
setAttribute(Qt::WA_NativeWindow, true);
|
||||||
|
setAttribute(Qt::WA_PaintOnScreen, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QtDisplayWidget::~QtDisplayWidget() = default;
|
||||||
|
|
||||||
|
HostDisplay* QtDisplayWidget::getHostDisplayInterface()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtDisplayWidget::hasDeviceContext() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtDisplayWidget::createDeviceContext(QThread* worker_thread, bool debug_device)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtDisplayWidget::initializeDeviceContext(bool debug_device)
|
||||||
|
{
|
||||||
|
if (!createImGuiContext() || !createDeviceResources())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtDisplayWidget::destroyDeviceContext()
|
||||||
|
{
|
||||||
|
destroyImGuiContext();
|
||||||
|
destroyDeviceResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal QtDisplayWidget::getDevicePixelRatioFromScreen() const
|
||||||
|
{
|
||||||
|
QScreen* screen_for_ratio;
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||||
|
screen_for_ratio = windowHandle()->screen();
|
||||||
|
#else
|
||||||
|
screen_for_ratio = screen();
|
||||||
|
#endif
|
||||||
|
if (!screen_for_ratio)
|
||||||
|
screen_for_ratio = QGuiApplication::primaryScreen();
|
||||||
|
|
||||||
|
return screen_for_ratio ? screen_for_ratio->devicePixelRatio() : static_cast<qreal>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int QtDisplayWidget::getScaledWindowWidth() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(std::ceil(static_cast<qreal>(width()) * getDevicePixelRatioFromScreen()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int QtDisplayWidget::getScaledWindowHeight() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(std::ceil(static_cast<qreal>(height()) * getDevicePixelRatioFromScreen()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtDisplayWidget::createImGuiContext()
|
||||||
|
{
|
||||||
|
ImGui::CreateContext();
|
||||||
|
|
||||||
|
auto& io = ImGui::GetIO();
|
||||||
|
io.IniFilename = nullptr;
|
||||||
|
io.DisplaySize.x = static_cast<float>(getScaledWindowWidth());
|
||||||
|
io.DisplaySize.y = static_cast<float>(getScaledWindowHeight());
|
||||||
|
|
||||||
|
const float framebuffer_scale = static_cast<float>(getDevicePixelRatioFromScreen());
|
||||||
|
io.DisplayFramebufferScale.x = framebuffer_scale;
|
||||||
|
io.DisplayFramebufferScale.y = framebuffer_scale;
|
||||||
|
io.FontGlobalScale = framebuffer_scale;
|
||||||
|
ImGui::GetStyle().ScaleAllSizes(framebuffer_scale);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtDisplayWidget::destroyImGuiContext()
|
||||||
|
{
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtDisplayWidget::createDeviceResources()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtDisplayWidget::destroyDeviceResources() {}
|
||||||
|
|
||||||
|
void QtDisplayWidget::windowResized(s32 new_window_width, s32 new_window_height)
|
||||||
|
{
|
||||||
|
// imgui may not have been initialized yet
|
||||||
|
if (!ImGui::GetCurrentContext())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto& io = ImGui::GetIO();
|
||||||
|
io.DisplaySize.x = static_cast<float>(new_window_width);
|
||||||
|
io.DisplaySize.y = static_cast<float>(new_window_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPaintEngine* QtDisplayWidget::paintEngine() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtDisplayWidget::event(QEvent* event)
|
||||||
|
{
|
||||||
|
switch (event->type())
|
||||||
|
{
|
||||||
|
case QEvent::KeyPress:
|
||||||
|
case QEvent::KeyRelease:
|
||||||
|
{
|
||||||
|
QKeyEvent* key_event = static_cast<QKeyEvent*>(event);
|
||||||
|
if (!key_event->isAutoRepeat())
|
||||||
|
m_host_interface->handleKeyEvent(QtUtils::KeyEventToInt(key_event), event->type() == QEvent::KeyPress);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QEvent::Resize:
|
||||||
|
{
|
||||||
|
QWidget::event(event);
|
||||||
|
|
||||||
|
emit windowResizedEvent(getScaledWindowWidth(), getScaledWindowHeight());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return QWidget::event(event);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QtGui/QWindow>
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
#include <QtWidgets/QWidget>
|
||||||
|
|
||||||
class QKeyEvent;
|
class QKeyEvent;
|
||||||
class QResizeEvent;
|
class QResizeEvent;
|
||||||
|
@ -9,13 +9,13 @@ class HostDisplay;
|
||||||
|
|
||||||
class QtHostInterface;
|
class QtHostInterface;
|
||||||
|
|
||||||
class QtDisplayWindow : public QWindow
|
class QtDisplayWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QtDisplayWindow(QtHostInterface* host_interface, QWindow* parent);
|
QtDisplayWidget(QtHostInterface* host_interface, QWidget* parent);
|
||||||
virtual ~QtDisplayWindow();
|
virtual ~QtDisplayWidget();
|
||||||
|
|
||||||
virtual HostDisplay* getHostDisplayInterface();
|
virtual HostDisplay* getHostDisplayInterface();
|
||||||
|
|
||||||
|
@ -27,23 +27,24 @@ public:
|
||||||
virtual void Render() = 0;
|
virtual void Render() = 0;
|
||||||
|
|
||||||
// this comes back on the emu thread
|
// this comes back on the emu thread
|
||||||
virtual void WindowResized(s32 new_window_width, s32 new_window_height);
|
virtual void windowResized(s32 new_window_width, s32 new_window_height);
|
||||||
|
|
||||||
|
virtual QPaintEngine* paintEngine() const override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void windowResizedEvent(int width, int height);
|
void windowResizedEvent(int width, int height);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int getScaledWindowWidth() const { return static_cast<int>(static_cast<qreal>(width()) * devicePixelRatio()); }
|
qreal getDevicePixelRatioFromScreen() const;
|
||||||
int getScaledWindowHeight() const { return static_cast<int>(static_cast<qreal>(height()) * devicePixelRatio()); }
|
int getScaledWindowWidth() const;
|
||||||
|
int getScaledWindowHeight() const;
|
||||||
|
|
||||||
virtual bool createImGuiContext();
|
virtual bool createImGuiContext();
|
||||||
virtual void destroyImGuiContext();
|
virtual void destroyImGuiContext();
|
||||||
virtual bool createDeviceResources();
|
virtual bool createDeviceResources();
|
||||||
virtual void destroyDeviceResources();
|
virtual void destroyDeviceResources();
|
||||||
|
|
||||||
virtual void keyPressEvent(QKeyEvent* event) override;
|
virtual bool event(QEvent* event) override;
|
||||||
virtual void keyReleaseEvent(QKeyEvent* event) override;
|
|
||||||
virtual void resizeEvent(QResizeEvent* event) override;
|
|
||||||
|
|
||||||
QtHostInterface* m_host_interface;
|
QtHostInterface* m_host_interface;
|
||||||
};
|
};
|
|
@ -1,107 +0,0 @@
|
||||||
#include "qtdisplaywindow.h"
|
|
||||||
#include "imgui.h"
|
|
||||||
#include "qthostinterface.h"
|
|
||||||
#include "qtutils.h"
|
|
||||||
#include <QtGui/QKeyEvent>
|
|
||||||
|
|
||||||
QtDisplayWindow::QtDisplayWindow(QtHostInterface* host_interface, QWindow* parent)
|
|
||||||
: QWindow(parent), m_host_interface(host_interface)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QtDisplayWindow::~QtDisplayWindow() = default;
|
|
||||||
|
|
||||||
HostDisplay* QtDisplayWindow::getHostDisplayInterface()
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QtDisplayWindow::hasDeviceContext() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QtDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_device)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QtDisplayWindow::initializeDeviceContext(bool debug_device)
|
|
||||||
{
|
|
||||||
if (!createImGuiContext() || !createDeviceResources())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtDisplayWindow::destroyDeviceContext()
|
|
||||||
{
|
|
||||||
destroyImGuiContext();
|
|
||||||
destroyDeviceResources();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QtDisplayWindow::createImGuiContext()
|
|
||||||
{
|
|
||||||
ImGui::CreateContext();
|
|
||||||
|
|
||||||
auto& io = ImGui::GetIO();
|
|
||||||
io.IniFilename = nullptr;
|
|
||||||
io.DisplaySize.x = static_cast<float>(getScaledWindowWidth());
|
|
||||||
io.DisplaySize.y = static_cast<float>(getScaledWindowHeight());
|
|
||||||
|
|
||||||
const float framebuffer_scale = static_cast<float>(devicePixelRatio());
|
|
||||||
io.DisplayFramebufferScale.x = framebuffer_scale;
|
|
||||||
io.DisplayFramebufferScale.y = framebuffer_scale;
|
|
||||||
io.FontGlobalScale = framebuffer_scale;
|
|
||||||
ImGui::GetStyle().ScaleAllSizes(framebuffer_scale);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtDisplayWindow::destroyImGuiContext()
|
|
||||||
{
|
|
||||||
ImGui::DestroyContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QtDisplayWindow::createDeviceResources()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtDisplayWindow::destroyDeviceResources() {}
|
|
||||||
|
|
||||||
void QtDisplayWindow::WindowResized(s32 new_window_width, s32 new_window_height)
|
|
||||||
{
|
|
||||||
// imgui may not have been initialized yet
|
|
||||||
if (!ImGui::GetCurrentContext())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto& io = ImGui::GetIO();
|
|
||||||
io.DisplaySize.x = static_cast<float>(new_window_width);
|
|
||||||
io.DisplaySize.y = static_cast<float>(new_window_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtDisplayWindow::keyPressEvent(QKeyEvent* event)
|
|
||||||
{
|
|
||||||
if (event->isAutoRepeat())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_host_interface->handleKeyEvent(QtUtils::KeyEventToInt(event), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtDisplayWindow::keyReleaseEvent(QKeyEvent* event)
|
|
||||||
{
|
|
||||||
if (event->isAutoRepeat())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_host_interface->handleKeyEvent(QtUtils::KeyEventToInt(event), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtDisplayWindow::resizeEvent(QResizeEvent* event)
|
|
||||||
{
|
|
||||||
QWindow::resizeEvent(event);
|
|
||||||
|
|
||||||
const int width = static_cast<int>(static_cast<qreal>(event->size().width()) * devicePixelRatio());
|
|
||||||
const int height = static_cast<int>(static_cast<qreal>(event->size().height()) * devicePixelRatio());
|
|
||||||
emit windowResizedEvent(width, height);
|
|
||||||
}
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "core/system.h"
|
#include "core/system.h"
|
||||||
#include "frontend-common/sdl_audio_stream.h"
|
#include "frontend-common/sdl_audio_stream.h"
|
||||||
#include "frontend-common/sdl_controller_interface.h"
|
#include "frontend-common/sdl_controller_interface.h"
|
||||||
|
#include "opengldisplaywidget.h"
|
||||||
#include "qtsettingsinterface.h"
|
#include "qtsettingsinterface.h"
|
||||||
#include "qtutils.h"
|
#include "qtutils.h"
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
|
@ -23,7 +24,7 @@
|
||||||
Log_SetChannel(QtHostInterface);
|
Log_SetChannel(QtHostInterface);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include "d3d11displaywindow.h"
|
#include "d3d11displaywidget.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QtHostInterface::QtHostInterface(QObject* parent)
|
QtHostInterface::QtHostInterface(QObject* parent)
|
||||||
|
@ -39,7 +40,7 @@ QtHostInterface::QtHostInterface(QObject* parent)
|
||||||
|
|
||||||
QtHostInterface::~QtHostInterface()
|
QtHostInterface::~QtHostInterface()
|
||||||
{
|
{
|
||||||
Assert(!m_display_window);
|
Assert(!m_display_widget);
|
||||||
stopThread();
|
stopThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,20 +136,20 @@ void QtHostInterface::refreshGameList(bool invalidate_cache /* = false */, bool
|
||||||
emit gameListRefreshed();
|
emit gameListRefreshed();
|
||||||
}
|
}
|
||||||
|
|
||||||
QtDisplayWindow* QtHostInterface::createDisplayWindow()
|
QtDisplayWidget* QtHostInterface::createDisplayWidget()
|
||||||
{
|
{
|
||||||
Assert(!m_display_window);
|
Assert(!m_display_widget);
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
if (m_settings.gpu_renderer == GPURenderer::HardwareOpenGL)
|
if (m_settings.gpu_renderer == GPURenderer::HardwareOpenGL)
|
||||||
m_display_window = new OpenGLDisplayWindow(this, nullptr);
|
m_display_widget = new OpenGLDisplayWidget(this, nullptr);
|
||||||
else
|
else
|
||||||
m_display_window = new D3D11DisplayWindow(this, nullptr);
|
m_display_widget = new D3D11DisplayWidget(this, nullptr);
|
||||||
#else
|
#else
|
||||||
m_display_window = new OpenGLDisplayWindow(this, nullptr);
|
m_display_widget = new OpenGLDisplayWidget(this, nullptr);
|
||||||
#endif
|
#endif
|
||||||
connect(m_display_window, &QtDisplayWindow::windowResizedEvent, this, &QtHostInterface::onDisplayWindowResized);
|
connect(m_display_widget, &QtDisplayWidget::windowResizedEvent, this, &QtHostInterface::onDisplayWidgetResized);
|
||||||
return m_display_window;
|
return m_display_widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHostInterface::bootSystem(const SystemBootParameters& params)
|
void QtHostInterface::bootSystem(const SystemBootParameters& params)
|
||||||
|
@ -188,43 +189,43 @@ void QtHostInterface::handleKeyEvent(int key, bool pressed)
|
||||||
HandleHostKeyEvent(key, pressed);
|
HandleHostKeyEvent(key, pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHostInterface::onDisplayWindowResized(int width, int height)
|
void QtHostInterface::onDisplayWidgetResized(int width, int height)
|
||||||
{
|
{
|
||||||
// this can be null if it was destroyed and the main thread is late catching up
|
// this can be null if it was destroyed and the main thread is late catching up
|
||||||
if (m_display_window)
|
if (m_display_widget)
|
||||||
m_display_window->WindowResized(width, height);
|
m_display_widget->windowResized(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtHostInterface::AcquireHostDisplay()
|
bool QtHostInterface::AcquireHostDisplay()
|
||||||
{
|
{
|
||||||
DebugAssert(!m_display_window);
|
DebugAssert(!m_display_widget);
|
||||||
|
|
||||||
emit createDisplayWindowRequested(m_worker_thread, m_settings.gpu_use_debug_device);
|
emit createDisplayWindowRequested(m_worker_thread, m_settings.gpu_use_debug_device);
|
||||||
if (!m_display_window->hasDeviceContext())
|
if (!m_display_widget->hasDeviceContext())
|
||||||
{
|
{
|
||||||
m_display_window = nullptr;
|
m_display_widget = nullptr;
|
||||||
emit destroyDisplayWindowRequested();
|
emit destroyDisplayWindowRequested();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_display_window->initializeDeviceContext(m_settings.gpu_use_debug_device))
|
if (!m_display_widget->initializeDeviceContext(m_settings.gpu_use_debug_device))
|
||||||
{
|
{
|
||||||
m_display_window->destroyDeviceContext();
|
m_display_widget->destroyDeviceContext();
|
||||||
m_display_window = nullptr;
|
m_display_widget = nullptr;
|
||||||
emit destroyDisplayWindowRequested();
|
emit destroyDisplayWindowRequested();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_display = m_display_window->getHostDisplayInterface();
|
m_display = m_display_widget->getHostDisplayInterface();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHostInterface::ReleaseHostDisplay()
|
void QtHostInterface::ReleaseHostDisplay()
|
||||||
{
|
{
|
||||||
DebugAssert(m_display_window && m_display == m_display_window->getHostDisplayInterface());
|
DebugAssert(m_display_widget && m_display == m_display_widget->getHostDisplayInterface());
|
||||||
m_display = nullptr;
|
m_display = nullptr;
|
||||||
m_display_window->destroyDeviceContext();
|
m_display_widget->destroyDeviceContext();
|
||||||
m_display_window = nullptr;
|
m_display_widget = nullptr;
|
||||||
emit destroyDisplayWindowRequested();
|
emit destroyDisplayWindowRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include "core/host_interface.h"
|
#include "core/host_interface.h"
|
||||||
#include "core/system.h"
|
#include "core/system.h"
|
||||||
#include "frontend-common/common_host_interface.h"
|
#include "frontend-common/common_host_interface.h"
|
||||||
#include "opengldisplaywindow.h"
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QtCore/QByteArray>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QSettings>
|
#include <QtCore/QSettings>
|
||||||
|
@ -24,6 +23,8 @@ class QTimer;
|
||||||
|
|
||||||
class GameList;
|
class GameList;
|
||||||
|
|
||||||
|
class QtDisplayWidget;
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(SystemBootParameters);
|
Q_DECLARE_METATYPE(SystemBootParameters);
|
||||||
|
|
||||||
class QtHostInterface : public QObject, private CommonHostInterface
|
class QtHostInterface : public QObject, private CommonHostInterface
|
||||||
|
@ -51,7 +52,7 @@ public:
|
||||||
|
|
||||||
bool isOnWorkerThread() const { return QThread::currentThread() == m_worker_thread; }
|
bool isOnWorkerThread() const { return QThread::currentThread() == m_worker_thread; }
|
||||||
|
|
||||||
QtDisplayWindow* createDisplayWindow();
|
QtDisplayWidget* createDisplayWidget();
|
||||||
|
|
||||||
void populateSaveStateMenus(const char* game_code, QMenu* load_menu, QMenu* save_menu);
|
void populateSaveStateMenus(const char* game_code, QMenu* load_menu, QMenu* save_menu);
|
||||||
|
|
||||||
|
@ -101,7 +102,7 @@ public Q_SLOTS:
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void doStopThread();
|
void doStopThread();
|
||||||
void onDisplayWindowResized(int width, int height);
|
void onDisplayWidgetResized(int width, int height);
|
||||||
void doBackgroundControllerPoll();
|
void doBackgroundControllerPoll();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -155,7 +156,7 @@ private:
|
||||||
QSettings m_qsettings;
|
QSettings m_qsettings;
|
||||||
std::mutex m_qsettings_mutex;
|
std::mutex m_qsettings_mutex;
|
||||||
|
|
||||||
QtDisplayWindow* m_display_window = nullptr;
|
QtDisplayWidget* m_display_widget = nullptr;
|
||||||
QThread* m_original_thread = nullptr;
|
QThread* m_original_thread = nullptr;
|
||||||
Thread* m_worker_thread = nullptr;
|
Thread* m_worker_thread = nullptr;
|
||||||
QEventLoop* m_worker_thread_event_loop = nullptr;
|
QEventLoop* m_worker_thread_event_loop = nullptr;
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
Log_SetChannel(OpenGLHostDisplay);
|
Log_SetChannel(OpenGLHostDisplay);
|
||||||
|
|
||||||
class OpenGLHostDisplayTexture : public HostDisplayTexture
|
class OpenGLDisplayWidgetTexture : public HostDisplayTexture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OpenGLHostDisplayTexture(GLuint id, u32 width, u32 height) : m_id(id), m_width(width), m_height(height) {}
|
OpenGLDisplayWidgetTexture(GLuint id, u32 width, u32 height) : m_id(id), m_width(width), m_height(height) {}
|
||||||
~OpenGLHostDisplayTexture() override { glDeleteTextures(1, &m_id); }
|
~OpenGLDisplayWidgetTexture() override { glDeleteTextures(1, &m_id); }
|
||||||
|
|
||||||
void* GetHandle() const override { return reinterpret_cast<void*>(static_cast<uintptr_t>(m_id)); }
|
void* GetHandle() const override { return reinterpret_cast<void*>(static_cast<uintptr_t>(m_id)); }
|
||||||
u32 GetWidth() const override { return m_width; }
|
u32 GetWidth() const override { return m_width; }
|
||||||
|
@ -20,7 +20,7 @@ public:
|
||||||
|
|
||||||
GLuint GetGLID() const { return m_id; }
|
GLuint GetGLID() const { return m_id; }
|
||||||
|
|
||||||
static std::unique_ptr<OpenGLHostDisplayTexture> Create(u32 width, u32 height, const void* initial_data,
|
static std::unique_ptr<OpenGLDisplayWidgetTexture> Create(u32 width, u32 height, const void* initial_data,
|
||||||
u32 initial_data_stride)
|
u32 initial_data_stride)
|
||||||
{
|
{
|
||||||
GLuint id;
|
GLuint id;
|
||||||
|
@ -39,7 +39,7 @@ public:
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
return std::make_unique<OpenGLHostDisplayTexture>(id, width, height);
|
return std::make_unique<OpenGLDisplayWidgetTexture>(id, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -111,13 +111,13 @@ void OpenGLHostDisplay::WindowResized(s32 new_window_width, s32 new_window_heigh
|
||||||
std::unique_ptr<HostDisplayTexture> OpenGLHostDisplay::CreateTexture(u32 width, u32 height, const void* data,
|
std::unique_ptr<HostDisplayTexture> OpenGLHostDisplay::CreateTexture(u32 width, u32 height, const void* data,
|
||||||
u32 data_stride, bool dynamic)
|
u32 data_stride, bool dynamic)
|
||||||
{
|
{
|
||||||
return OpenGLHostDisplayTexture::Create(width, height, data, data_stride);
|
return OpenGLDisplayWidgetTexture::Create(width, height, data, data_stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLHostDisplay::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height,
|
void OpenGLHostDisplay::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height,
|
||||||
const void* data, u32 data_stride)
|
const void* data, u32 data_stride)
|
||||||
{
|
{
|
||||||
OpenGLHostDisplayTexture* tex = static_cast<OpenGLHostDisplayTexture*>(texture);
|
OpenGLDisplayWidgetTexture* tex = static_cast<OpenGLDisplayWidgetTexture*>(texture);
|
||||||
Assert(data_stride == (width * sizeof(u32)));
|
Assert(data_stride == (width * sizeof(u32)));
|
||||||
|
|
||||||
GLint old_texture_binding = 0;
|
GLint old_texture_binding = 0;
|
||||||
|
|
Loading…
Reference in a new issue