mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 23:55:40 +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.h
|
||||
mainwindow.ui
|
||||
opengldisplaywindow.cpp
|
||||
opengldisplaywindow.h
|
||||
opengldisplaywidget.cpp
|
||||
opengldisplaywidget.h
|
||||
portsettingswidget.cpp
|
||||
portsettingswidget.h
|
||||
qtdisplaywindow.cpp
|
||||
qtdisplaywindow.h
|
||||
qtdisplaywidget.cpp
|
||||
qtdisplaywidget.h
|
||||
qthostinterface.cpp
|
||||
qthostinterface.h
|
||||
qtsettingsinterface.cpp
|
||||
|
@ -47,8 +47,8 @@ target_link_libraries(duckstation-qt PRIVATE frontend-common core common imgui g
|
|||
|
||||
if(WIN32)
|
||||
target_sources(duckstation-qt PRIVATE
|
||||
d3d11displaywindow.cpp
|
||||
d3d11displaywindow.h
|
||||
d3d11displaywidget.cpp
|
||||
d3d11displaywidget.h
|
||||
)
|
||||
target_link_libraries(duckstation PRIVATE d3d11.lib dxgi.lib)
|
||||
endif()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "d3d11displaywindow.h"
|
||||
#include "d3d11displaywidget.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/d3d11/shader_compiler.h"
|
||||
#include "common/log.h"
|
||||
|
@ -8,20 +8,20 @@
|
|||
#include <dxgi1_5.h>
|
||||
#include <imgui.h>
|
||||
#include <imgui_impl_dx11.h>
|
||||
Log_SetChannel(D3D11DisplayWindow);
|
||||
Log_SetChannel(D3D11DisplayWidget);
|
||||
|
||||
class D3D11DisplayWindowTexture : public HostDisplayTexture
|
||||
class D3D11DisplayWidgetTexture : public HostDisplayTexture
|
||||
{
|
||||
public:
|
||||
template<typename 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)
|
||||
: 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(); }
|
||||
u32 GetWidth() const override { return m_width; }
|
||||
|
@ -31,7 +31,7 @@ public:
|
|||
ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); }
|
||||
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 CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, D3D11_BIND_SHADER_RESOURCE,
|
||||
|
@ -50,7 +50,7 @@ public:
|
|||
if (FAILED(hr))
|
||||
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:
|
||||
|
@ -61,76 +61,58 @@ private:
|
|||
bool m_dynamic;
|
||||
};
|
||||
|
||||
D3D11DisplayWindow::D3D11DisplayWindow(QtHostInterface* host_interface, QWindow* parent)
|
||||
: QtDisplayWindow(host_interface, parent)
|
||||
D3D11DisplayWidget::D3D11DisplayWidget(QtHostInterface* host_interface, QWidget* parent)
|
||||
: QtDisplayWidget(host_interface, parent)
|
||||
{
|
||||
}
|
||||
|
||||
D3D11DisplayWindow::~D3D11DisplayWindow() = default;
|
||||
D3D11DisplayWidget::~D3D11DisplayWidget() = default;
|
||||
|
||||
HostDisplay* D3D11DisplayWindow::getHostDisplayInterface()
|
||||
HostDisplay* D3D11DisplayWidget::getHostDisplayInterface()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
HostDisplay::RenderAPI D3D11DisplayWindow::GetRenderAPI() const
|
||||
HostDisplay::RenderAPI D3D11DisplayWidget::GetRenderAPI() const
|
||||
{
|
||||
return HostDisplay::RenderAPI::D3D11;
|
||||
}
|
||||
|
||||
void* D3D11DisplayWindow::GetRenderDevice() const
|
||||
void* D3D11DisplayWidget::GetRenderDevice() const
|
||||
{
|
||||
return m_device.Get();
|
||||
}
|
||||
|
||||
void* D3D11DisplayWindow::GetRenderContext() const
|
||||
void* D3D11DisplayWidget::GetRenderContext() const
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
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");
|
||||
return D3D11DisplayWidgetTexture::Create(m_device.Get(), width, height, initial_data, initial_data_stride, dynamic);
|
||||
}
|
||||
|
||||
std::unique_ptr<HostDisplayTexture> D3D11DisplayWindow::CreateTexture(u32 width, u32 height, const void* data,
|
||||
u32 data_stride, bool dynamic)
|
||||
void D3D11DisplayWidget::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height,
|
||||
const void* texture_data, u32 texture_data_stride)
|
||||
{
|
||||
return D3D11DisplayWindowTexture::Create(m_device.Get(), width, height, data, data_stride, dynamic);
|
||||
}
|
||||
|
||||
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);
|
||||
D3D11DisplayWidgetTexture* d3d11_texture = static_cast<D3D11DisplayWidgetTexture*>(texture);
|
||||
if (!d3d11_texture->IsDynamic())
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -140,17 +122,17 @@ void D3D11DisplayWindow::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y
|
|||
Panic("Failed to map dynamic host display texture");
|
||||
|
||||
char* dst_ptr = static_cast<char*>(sr.pData) + (y * sr.RowPitch) + (x * sizeof(u32));
|
||||
const char* src_ptr = static_cast<const char*>(data);
|
||||
if (sr.RowPitch == data_stride)
|
||||
const char* src_ptr = static_cast<const char*>(texture_data);
|
||||
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
|
||||
{
|
||||
for (u32 row = 0; row < height; row++)
|
||||
{
|
||||
std::memcpy(dst_ptr, src_ptr, width * sizeof(u32));
|
||||
src_ptr += data_stride;
|
||||
src_ptr += texture_data_stride;
|
||||
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;
|
||||
}
|
||||
|
||||
bool D3D11DisplayWindow::hasDeviceContext() const
|
||||
bool D3D11DisplayWidget::hasDeviceContext() const
|
||||
{
|
||||
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;
|
||||
if (debug_device)
|
||||
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
|
||||
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0, D3D11_SDK_VERSION,
|
||||
m_device.GetAddressOf(), nullptr, m_context.GetAddressOf());
|
||||
HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0,
|
||||
D3D11_SDK_VERSION, m_device.GetAddressOf(), nullptr, m_context.GetAddressOf());
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
@ -204,40 +166,6 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_
|
|||
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)
|
||||
{
|
||||
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_context.Reset();
|
||||
|
@ -259,26 +226,86 @@ bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_
|
|||
return true;
|
||||
}
|
||||
|
||||
bool D3D11DisplayWindow::initializeDeviceContext(bool debug_device)
|
||||
bool D3D11DisplayWidget::initializeDeviceContext(bool debug_device)
|
||||
{
|
||||
if (!createSwapChainRTV())
|
||||
return false;
|
||||
|
||||
if (!QtDisplayWindow::initializeDeviceContext(debug_device))
|
||||
if (!QtDisplayWidget::initializeDeviceContext(debug_device))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void D3D11DisplayWindow::destroyDeviceContext()
|
||||
void D3D11DisplayWidget::destroyDeviceContext()
|
||||
{
|
||||
QtDisplayWindow::destroyDeviceContext();
|
||||
QtDisplayWidget::destroyDeviceContext();
|
||||
m_swap_chain.Reset();
|
||||
m_context.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;
|
||||
HRESULT hr = m_swap_chain->GetBuffer(0, IID_PPV_ARGS(backbuffer.GetAddressOf()));
|
||||
|
@ -303,7 +330,7 @@ bool D3D11DisplayWindow::createSwapChainRTV()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool D3D11DisplayWindow::createDeviceResources()
|
||||
bool D3D11DisplayWidget::createDeviceResources()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -349,9 +376,9 @@ bool D3D11DisplayWindow::createDeviceResources()
|
|||
return true;
|
||||
}
|
||||
|
||||
void D3D11DisplayWindow::destroyDeviceResources()
|
||||
void D3D11DisplayWidget::destroyDeviceResources()
|
||||
{
|
||||
QtDisplayWindow::destroyDeviceResources();
|
||||
QtDisplayWidget::destroyDeviceResources();
|
||||
|
||||
m_display_uniform_buffer.Release();
|
||||
m_swap_chain_rtv.Reset();
|
||||
|
@ -364,9 +391,9 @@ void D3D11DisplayWindow::destroyDeviceResources()
|
|||
m_display_rasterizer_state.Reset();
|
||||
}
|
||||
|
||||
bool D3D11DisplayWindow::createImGuiContext()
|
||||
bool D3D11DisplayWidget::createImGuiContext()
|
||||
{
|
||||
if (!QtDisplayWindow::createImGuiContext())
|
||||
if (!QtDisplayWidget::createImGuiContext())
|
||||
return false;
|
||||
|
||||
if (!ImGui_ImplDX11_Init(m_device.Get(), m_context.Get()))
|
||||
|
@ -377,13 +404,13 @@ bool D3D11DisplayWindow::createImGuiContext()
|
|||
return true;
|
||||
}
|
||||
|
||||
void D3D11DisplayWindow::destroyImGuiContext()
|
||||
void D3D11DisplayWidget::destroyImGuiContext()
|
||||
{
|
||||
ImGui_ImplDX11_Shutdown();
|
||||
QtDisplayWindow::destroyImGuiContext();
|
||||
QtDisplayWidget::destroyImGuiContext();
|
||||
}
|
||||
|
||||
void D3D11DisplayWindow::Render()
|
||||
void D3D11DisplayWidget::Render()
|
||||
{
|
||||
static constexpr std::array<float, 4> clear_color = {};
|
||||
m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color.data());
|
||||
|
@ -403,7 +430,7 @@ void D3D11DisplayWindow::Render()
|
|||
ImGui_ImplDX11_NewFrame();
|
||||
}
|
||||
|
||||
void D3D11DisplayWindow::renderDisplay()
|
||||
void D3D11DisplayWidget::renderDisplay()
|
||||
{
|
||||
if (!m_display_texture_handle)
|
||||
return;
|
|
@ -1,14 +1,15 @@
|
|||
#pragma once
|
||||
#include "common/windows_headers.h"
|
||||
#include "common/d3d11/stream_buffer.h"
|
||||
#include "common/d3d11/texture.h"
|
||||
#include "common/windows_headers.h"
|
||||
#include "core/host_display.h"
|
||||
#include "qtdisplaywindow.h"
|
||||
#include "qtdisplaywidget.h"
|
||||
#include <d3d11.h>
|
||||
#include <dxgi.h>
|
||||
#include <memory>
|
||||
#include <wrl/client.h>
|
||||
|
||||
class D3D11DisplayWindow final : public QtDisplayWindow, private HostDisplay
|
||||
class D3D11DisplayWidget final : public QtDisplayWidget, private HostDisplay
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -16,8 +17,8 @@ public:
|
|||
template<typename T>
|
||||
using ComPtr = Microsoft::WRL::ComPtr<T>;
|
||||
|
||||
D3D11DisplayWindow(QtHostInterface* host_interface, QWindow* parent);
|
||||
~D3D11DisplayWindow();
|
||||
D3D11DisplayWidget(QtHostInterface* host_interface, QWidget* parent);
|
||||
~D3D11DisplayWidget();
|
||||
|
||||
HostDisplay* getHostDisplayInterface() override;
|
||||
|
||||
|
@ -32,12 +33,12 @@ public:
|
|||
void* GetRenderWindow() const 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,
|
||||
bool dynamic) override;
|
||||
void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data,
|
||||
u32 data_stride) override;
|
||||
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* initial_data,
|
||||
u32 initial_data_stride, bool dynamic) override;
|
||||
void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* texture_data,
|
||||
u32 texture_data_stride) override;
|
||||
|
||||
void SetVSync(bool enabled) override;
|
||||
|
||||
|
@ -51,10 +52,13 @@ private:
|
|||
bool createDeviceResources() override;
|
||||
void destroyDeviceResources() override;
|
||||
|
||||
bool createSwapChain(HWND hwnd);
|
||||
bool createSwapChainRTV();
|
||||
|
||||
void renderDisplay();
|
||||
|
||||
ComPtr<IDXGIFactory> m_dxgi_factory;
|
||||
|
||||
ComPtr<ID3D11Device> m_device;
|
||||
ComPtr<ID3D11DeviceContext> m_context;
|
||||
ComPtr<IDXGISwapChain> m_swap_chain;
|
|
@ -37,16 +37,16 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="audiosettingswidget.cpp" />
|
||||
<ClCompile Include="consolesettingswidget.cpp" />
|
||||
<ClCompile Include="d3d11displaywindow.cpp" />
|
||||
<ClCompile Include="d3d11displaywidget.cpp" />
|
||||
<ClCompile Include="gpusettingswidget.cpp" />
|
||||
<ClCompile Include="hotkeysettingswidget.cpp" />
|
||||
<ClCompile Include="inputbindingwidgets.cpp" />
|
||||
<ClCompile Include="qtdisplaywindow.cpp" />
|
||||
<ClCompile Include="qtdisplaywidget.cpp" />
|
||||
<ClCompile Include="gamelistsettingswidget.cpp" />
|
||||
<ClCompile Include="gamelistwidget.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="mainwindow.cpp" />
|
||||
<ClCompile Include="opengldisplaywindow.cpp" />
|
||||
<ClCompile Include="opengldisplaywidget.cpp" />
|
||||
<ClCompile Include="portsettingswidget.cpp" />
|
||||
<ClCompile Include="qthostinterface.cpp" />
|
||||
<ClCompile Include="qtsettingsinterface.cpp" />
|
||||
|
@ -56,17 +56,17 @@
|
|||
<ItemGroup>
|
||||
<QtMoc Include="audiosettingswidget.h" />
|
||||
<QtMoc Include="portsettingswidget.h" />
|
||||
<QtMoc Include="qtdisplaywindow.h" />
|
||||
<QtMoc Include="qtdisplaywidget.h" />
|
||||
<QtMoc Include="gpusettingswidget.h" />
|
||||
<QtMoc Include="hotkeysettingswidget.h" />
|
||||
<QtMoc Include="inputbindingwidgets.h" />
|
||||
<QtMoc Include="d3d11displaywindow.h" />
|
||||
<QtMoc Include="d3d11displaywidget.h" />
|
||||
<ClInclude Include="settingwidgetbinder.h" />
|
||||
<QtMoc Include="consolesettingswidget.h" />
|
||||
<QtMoc Include="gamelistsettingswidget.h" />
|
||||
<QtMoc Include="gamelistwidget.h" />
|
||||
<QtMoc Include="mainwindow.h" />
|
||||
<QtMoc Include="opengldisplaywindow.h" />
|
||||
<QtMoc Include="opengldisplaywidget.h" />
|
||||
<QtMoc Include="qthostinterface.h" />
|
||||
<ClInclude Include="qtsettingsinterface.h" />
|
||||
<ClInclude Include="qtutils.h" />
|
||||
|
@ -117,16 +117,16 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="$(IntDir)moc_audiosettingswidget.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_gamelistwidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_hotkeysettingswidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_inputbindingwidgets.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_qtdisplaywindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_qtdisplaywidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_qthostinterface.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_settingsdialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)qrc_icons.cpp" />
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<ClCompile Include="gamelistwidget.cpp" />
|
||||
<ClCompile Include="settingsdialog.cpp" />
|
||||
<ClCompile Include="consolesettingswidget.cpp" />
|
||||
<ClCompile Include="opengldisplaywindow.cpp" />
|
||||
<ClCompile Include="qthostinterface.cpp" />
|
||||
<ClCompile Include="gamelistsettingswidget.cpp" />
|
||||
<ClCompile Include="qtsettingsinterface.cpp" />
|
||||
|
@ -15,24 +14,25 @@
|
|||
<ClCompile Include="$(IntDir)moc_gamelistsettingswidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_gamelistwidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_mainwindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_opengldisplaywindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_qthostinterface.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_settingsdialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)qrc_icons.cpp" />
|
||||
<ClCompile Include="portsettingswidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_portsettingswidget.cpp" />
|
||||
<ClCompile Include="qtdisplaywindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_qtdisplaywindow.cpp" />
|
||||
<ClCompile Include="gpusettingswidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_gpusettingswidget.cpp" />
|
||||
<ClCompile Include="inputbindingwidgets.cpp" />
|
||||
<ClCompile Include="hotkeysettingswidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_hotkeysettingswidget.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_inputbindingwidgets.cpp" />
|
||||
<ClCompile Include="d3d11displaywindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_d3d11displaywindow.cpp" />
|
||||
<ClCompile Include="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>
|
||||
<ClInclude Include="qtsettingsinterface.h" />
|
||||
|
@ -52,16 +52,16 @@
|
|||
<QtMoc Include="gamelistsettingswidget.h" />
|
||||
<QtMoc Include="gamelistwidget.h" />
|
||||
<QtMoc Include="mainwindow.h" />
|
||||
<QtMoc Include="opengldisplaywindow.h" />
|
||||
<QtMoc Include="qthostinterface.h" />
|
||||
<QtMoc Include="settingsdialog.h" />
|
||||
<QtMoc Include="portsettingswidget.h" />
|
||||
<QtMoc Include="qtdisplaywindow.h" />
|
||||
<QtMoc Include="gpusettingswidget.h" />
|
||||
<QtMoc Include="hotkeysettingswidget.h" />
|
||||
<QtMoc Include="inputbindingwidgets.h" />
|
||||
<QtMoc Include="d3d11displaywindow.h" />
|
||||
<QtMoc Include="audiosettingswidget.h" />
|
||||
<QtMoc Include="opengldisplaywidget.h" />
|
||||
<QtMoc Include="d3d11displaywidget.h" />
|
||||
<QtMoc Include="qtdisplaywidget.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUi Include="consolesettingswidget.ui" />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "core/system.h"
|
||||
#include "gamelistsettingswidget.h"
|
||||
#include "gamelistwidget.h"
|
||||
#include "qtdisplaywindow.h"
|
||||
#include "qtdisplaywidget.h"
|
||||
#include "qthostinterface.h"
|
||||
#include "qtsettingsinterface.h"
|
||||
#include "settingsdialog.h"
|
||||
|
@ -57,10 +57,7 @@ void MainWindow::createDisplayWindow(QThread* worker_thread, bool use_debug_devi
|
|||
{
|
||||
DebugAssert(!m_display_widget);
|
||||
|
||||
QtDisplayWindow* display_window = m_host_interface->createDisplayWindow();
|
||||
DebugAssert(display_window);
|
||||
|
||||
m_display_widget = QWidget::createWindowContainer(display_window, m_ui.mainContainer);
|
||||
m_display_widget = m_host_interface->createDisplayWidget();
|
||||
DebugAssert(m_display_widget);
|
||||
|
||||
m_display_widget->setFocusPolicy(Qt::StrongFocus);
|
||||
|
@ -70,7 +67,7 @@ void MainWindow::createDisplayWindow(QThread* worker_thread, bool use_debug_devi
|
|||
switchToEmulationView();
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
display_window->createDeviceContext(worker_thread, use_debug_device);
|
||||
m_display_widget->createDeviceContext(worker_thread, use_debug_device);
|
||||
}
|
||||
|
||||
void MainWindow::destroyDisplayWindow()
|
||||
|
|
|
@ -12,6 +12,7 @@ class QThread;
|
|||
|
||||
class GameListWidget;
|
||||
class QtHostInterface;
|
||||
class QtDisplayWidget;
|
||||
|
||||
struct GameListEntry;
|
||||
|
||||
|
@ -71,7 +72,7 @@ private:
|
|||
QtHostInterface* m_host_interface = 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_fps_widget = nullptr;
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include "opengldisplaywindow.h"
|
||||
#include "opengldisplaywidget.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
#include "imgui.h"
|
||||
#include "qthostinterface.h"
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtGui/QWindow>
|
||||
#include <array>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
#include <tuple>
|
||||
Log_SetChannel(OpenGLDisplayWindow);
|
||||
Log_SetChannel(OpenGLDisplayWidget);
|
||||
|
||||
static thread_local QOpenGLContext* s_thread_gl_context;
|
||||
|
||||
|
@ -56,11 +57,11 @@ static void SetSwapInterval(QWindow* window, QOpenGLContext* context, int interv
|
|||
#endif
|
||||
}
|
||||
|
||||
class OpenGLHostDisplayTexture : public HostDisplayTexture
|
||||
class OpenGLDisplayWidgetTexture : public HostDisplayTexture
|
||||
{
|
||||
public:
|
||||
OpenGLHostDisplayTexture(GLuint id, u32 width, u32 height) : m_id(id), m_width(width), m_height(height) {}
|
||||
~OpenGLHostDisplayTexture() override { glDeleteTextures(1, &m_id); }
|
||||
OpenGLDisplayWidgetTexture(GLuint id, u32 width, u32 height) : m_id(id), m_width(width), m_height(height) {}
|
||||
~OpenGLDisplayWidgetTexture() override { glDeleteTextures(1, &m_id); }
|
||||
|
||||
void* GetHandle() const override { return reinterpret_cast<void*>(static_cast<uintptr_t>(m_id)); }
|
||||
u32 GetWidth() const override { return m_width; }
|
||||
|
@ -68,7 +69,7 @@ public:
|
|||
|
||||
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)
|
||||
{
|
||||
GLuint id;
|
||||
|
@ -87,7 +88,7 @@ public:
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
return std::make_unique<OpenGLHostDisplayTexture>(id, width, height);
|
||||
return std::make_unique<OpenGLDisplayWidgetTexture>(id, width, height);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -96,82 +97,84 @@ private:
|
|||
u32 m_height;
|
||||
};
|
||||
|
||||
OpenGLDisplayWindow::OpenGLDisplayWindow(QtHostInterface* host_interface, QWindow* parent)
|
||||
: QtDisplayWindow(host_interface, parent)
|
||||
OpenGLDisplayWidget::OpenGLDisplayWidget(QtHostInterface* host_interface, QWidget* 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;
|
||||
}
|
||||
|
||||
HostDisplay::RenderAPI OpenGLDisplayWindow::GetRenderAPI() const
|
||||
HostDisplay::RenderAPI OpenGLDisplayWidget::GetRenderAPI() const
|
||||
{
|
||||
return m_gl_context->isOpenGLES() ? HostDisplay::RenderAPI::OpenGLES : HostDisplay::RenderAPI::OpenGL;
|
||||
}
|
||||
|
||||
void* OpenGLDisplayWindow::GetRenderDevice() const
|
||||
void* OpenGLDisplayWidget::GetRenderDevice() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* OpenGLDisplayWindow::GetRenderContext() const
|
||||
void* OpenGLDisplayWidget::GetRenderContext() const
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::unique_ptr<HostDisplayTexture> OpenGLDisplayWindow::CreateTexture(u32 width, u32 height, const void* data,
|
||||
u32 data_stride, bool dynamic)
|
||||
std::unique_ptr<HostDisplayTexture> OpenGLDisplayWidget::CreateTexture(u32 width, u32 height, const void* initial_data,
|
||||
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,
|
||||
const void* data, u32 data_stride)
|
||||
void OpenGLDisplayWidget::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height,
|
||||
const void* texture_data, u32 texture_data_stride)
|
||||
{
|
||||
OpenGLHostDisplayTexture* tex = static_cast<OpenGLHostDisplayTexture*>(texture);
|
||||
Assert(data_stride == (width * sizeof(u32)));
|
||||
OpenGLDisplayWidgetTexture* tex = static_cast<OpenGLDisplayWidgetTexture*>(texture);
|
||||
Assert(texture_data_stride == (width * sizeof(u32)));
|
||||
|
||||
GLint old_texture_binding = 0;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_texture_binding);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void OpenGLDisplayWindow::SetVSync(bool enabled)
|
||||
void OpenGLDisplayWidget::SetVSync(bool enabled)
|
||||
{
|
||||
// Window framebuffer has to be bound to call SetSwapInterval.
|
||||
GLint current_fbo = 0;
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_fbo);
|
||||
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);
|
||||
}
|
||||
|
||||
const char* OpenGLDisplayWindow::GetGLSLVersionString() const
|
||||
const char* OpenGLDisplayWidget::GetGLSLVersionString() const
|
||||
{
|
||||
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();
|
||||
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);
|
||||
}
|
||||
|
||||
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>();
|
||||
|
||||
|
@ -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}}};
|
||||
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.setSwapInterval(0);
|
||||
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"),
|
||||
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");
|
||||
m_gl_context.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!QtDisplayWindow::createDeviceContext(worker_thread, debug_device))
|
||||
if (!QtDisplayWidget::createDeviceContext(worker_thread, debug_device))
|
||||
{
|
||||
m_gl_context->doneCurrent();
|
||||
m_gl_context.reset();
|
||||
|
@ -299,9 +302,9 @@ bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug
|
|||
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;
|
||||
|
||||
s_thread_gl_context = m_gl_context.get();
|
||||
|
@ -324,7 +327,7 @@ bool OpenGLDisplayWindow::initializeDeviceContext(bool debug_device)
|
|||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
}
|
||||
|
||||
if (!QtDisplayWindow::initializeDeviceContext(debug_device))
|
||||
if (!QtDisplayWidget::initializeDeviceContext(debug_device))
|
||||
{
|
||||
s_thread_gl_context = nullptr;
|
||||
m_gl_context->doneCurrent();
|
||||
|
@ -334,20 +337,20 @@ bool OpenGLDisplayWindow::initializeDeviceContext(bool debug_device)
|
|||
return true;
|
||||
}
|
||||
|
||||
void OpenGLDisplayWindow::destroyDeviceContext()
|
||||
void OpenGLDisplayWidget::destroyDeviceContext()
|
||||
{
|
||||
Assert(m_gl_context && s_thread_gl_context == m_gl_context.get());
|
||||
|
||||
QtDisplayWindow::destroyDeviceContext();
|
||||
QtDisplayWidget::destroyDeviceContext();
|
||||
|
||||
s_thread_gl_context = nullptr;
|
||||
m_gl_context->doneCurrent();
|
||||
m_gl_context.reset();
|
||||
}
|
||||
|
||||
bool OpenGLDisplayWindow::createImGuiContext()
|
||||
bool OpenGLDisplayWidget::createImGuiContext()
|
||||
{
|
||||
if (!QtDisplayWindow::createImGuiContext())
|
||||
if (!QtDisplayWidget::createImGuiContext())
|
||||
return false;
|
||||
|
||||
if (!ImGui_ImplOpenGL3_Init(GetGLSLVersionString()))
|
||||
|
@ -358,14 +361,14 @@ bool OpenGLDisplayWindow::createImGuiContext()
|
|||
return true;
|
||||
}
|
||||
|
||||
void OpenGLDisplayWindow::destroyImGuiContext()
|
||||
void OpenGLDisplayWidget::destroyImGuiContext()
|
||||
{
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
|
||||
QtDisplayWindow::destroyImGuiContext();
|
||||
QtDisplayWidget::destroyImGuiContext();
|
||||
}
|
||||
|
||||
bool OpenGLDisplayWindow::createDeviceResources()
|
||||
bool OpenGLDisplayWidget::createDeviceResources()
|
||||
{
|
||||
static constexpr char fullscreen_quad_vertex_shader[] = R"(
|
||||
uniform vec4 u_src_rect;
|
||||
|
@ -425,9 +428,9 @@ void main()
|
|||
return true;
|
||||
}
|
||||
|
||||
void OpenGLDisplayWindow::destroyDeviceResources()
|
||||
void OpenGLDisplayWidget::destroyDeviceResources()
|
||||
{
|
||||
QtDisplayWindow::destroyDeviceResources();
|
||||
QtDisplayWidget::destroyDeviceResources();
|
||||
|
||||
if (m_display_vao != 0)
|
||||
glDeleteVertexArrays(1, &m_display_vao);
|
||||
|
@ -439,7 +442,7 @@ void OpenGLDisplayWindow::destroyDeviceResources()
|
|||
m_display_program.Destroy();
|
||||
}
|
||||
|
||||
void OpenGLDisplayWindow::Render()
|
||||
void OpenGLDisplayWidget::Render()
|
||||
{
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
@ -451,8 +454,9 @@ void OpenGLDisplayWindow::Render()
|
|||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
m_gl_context->makeCurrent(this);
|
||||
m_gl_context->swapBuffers(this);
|
||||
QWindow* window_handle = windowHandle();
|
||||
m_gl_context->makeCurrent(window_handle);
|
||||
m_gl_context->swapBuffers(window_handle);
|
||||
|
||||
ImGui::NewFrame();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
|
@ -460,7 +464,7 @@ void OpenGLDisplayWindow::Render()
|
|||
GL::Program::ResetLastProgram();
|
||||
}
|
||||
|
||||
void OpenGLDisplayWindow::renderDisplay()
|
||||
void OpenGLDisplayWidget::renderDisplay()
|
||||
{
|
||||
if (!m_display_texture_handle)
|
||||
return;
|
|
@ -11,19 +11,19 @@
|
|||
#include "common/gl/program.h"
|
||||
#include "common/gl/texture.h"
|
||||
#include "core/host_display.h"
|
||||
#include "qtdisplaywindow.h"
|
||||
#include "qtdisplaywidget.h"
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <memory>
|
||||
|
||||
class QtHostInterface;
|
||||
|
||||
class OpenGLDisplayWindow final : public QtDisplayWindow, public HostDisplay
|
||||
class OpenGLDisplayWidget final : public QtDisplayWidget, public HostDisplay
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OpenGLDisplayWindow(QtHostInterface* host_interface, QWindow* parent);
|
||||
~OpenGLDisplayWindow();
|
||||
OpenGLDisplayWidget(QtHostInterface* host_interface, QWidget* parent);
|
||||
~OpenGLDisplayWidget();
|
||||
|
||||
HostDisplay* getHostDisplayInterface() override;
|
||||
|
||||
|
@ -38,12 +38,12 @@ public:
|
|||
void* GetRenderWindow() const 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,
|
||||
bool dynamic) override;
|
||||
void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data,
|
||||
u32 data_stride) override;
|
||||
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* initial_data,
|
||||
u32 initial_data_stride, bool dynamic) override;
|
||||
void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* texture_data,
|
||||
u32 texture_data_stride) 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
|
||||
#include <QtGui/QWindow>
|
||||
#include "common/types.h"
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class QKeyEvent;
|
||||
class QResizeEvent;
|
||||
|
@ -9,13 +9,13 @@ class HostDisplay;
|
|||
|
||||
class QtHostInterface;
|
||||
|
||||
class QtDisplayWindow : public QWindow
|
||||
class QtDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtDisplayWindow(QtHostInterface* host_interface, QWindow* parent);
|
||||
virtual ~QtDisplayWindow();
|
||||
QtDisplayWidget(QtHostInterface* host_interface, QWidget* parent);
|
||||
virtual ~QtDisplayWidget();
|
||||
|
||||
virtual HostDisplay* getHostDisplayInterface();
|
||||
|
||||
|
@ -27,23 +27,24 @@ public:
|
|||
virtual void Render() = 0;
|
||||
|
||||
// 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:
|
||||
void windowResizedEvent(int width, int height);
|
||||
|
||||
protected:
|
||||
int getScaledWindowWidth() const { return static_cast<int>(static_cast<qreal>(width()) * devicePixelRatio()); }
|
||||
int getScaledWindowHeight() const { return static_cast<int>(static_cast<qreal>(height()) * devicePixelRatio()); }
|
||||
qreal getDevicePixelRatioFromScreen() const;
|
||||
int getScaledWindowWidth() const;
|
||||
int getScaledWindowHeight() const;
|
||||
|
||||
virtual bool createImGuiContext();
|
||||
virtual void destroyImGuiContext();
|
||||
virtual bool createDeviceResources();
|
||||
virtual void destroyDeviceResources();
|
||||
|
||||
virtual void keyPressEvent(QKeyEvent* event) override;
|
||||
virtual void keyReleaseEvent(QKeyEvent* event) override;
|
||||
virtual void resizeEvent(QResizeEvent* event) override;
|
||||
virtual bool event(QEvent* event) override;
|
||||
|
||||
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 "frontend-common/sdl_audio_stream.h"
|
||||
#include "frontend-common/sdl_controller_interface.h"
|
||||
#include "opengldisplaywidget.h"
|
||||
#include "qtsettingsinterface.h"
|
||||
#include "qtutils.h"
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
@ -23,7 +24,7 @@
|
|||
Log_SetChannel(QtHostInterface);
|
||||
|
||||
#ifdef WIN32
|
||||
#include "d3d11displaywindow.h"
|
||||
#include "d3d11displaywidget.h"
|
||||
#endif
|
||||
|
||||
QtHostInterface::QtHostInterface(QObject* parent)
|
||||
|
@ -39,7 +40,7 @@ QtHostInterface::QtHostInterface(QObject* parent)
|
|||
|
||||
QtHostInterface::~QtHostInterface()
|
||||
{
|
||||
Assert(!m_display_window);
|
||||
Assert(!m_display_widget);
|
||||
stopThread();
|
||||
}
|
||||
|
||||
|
@ -135,20 +136,20 @@ void QtHostInterface::refreshGameList(bool invalidate_cache /* = false */, bool
|
|||
emit gameListRefreshed();
|
||||
}
|
||||
|
||||
QtDisplayWindow* QtHostInterface::createDisplayWindow()
|
||||
QtDisplayWidget* QtHostInterface::createDisplayWidget()
|
||||
{
|
||||
Assert(!m_display_window);
|
||||
Assert(!m_display_widget);
|
||||
|
||||
#ifdef WIN32
|
||||
if (m_settings.gpu_renderer == GPURenderer::HardwareOpenGL)
|
||||
m_display_window = new OpenGLDisplayWindow(this, nullptr);
|
||||
m_display_widget = new OpenGLDisplayWidget(this, nullptr);
|
||||
else
|
||||
m_display_window = new D3D11DisplayWindow(this, nullptr);
|
||||
m_display_widget = new D3D11DisplayWidget(this, nullptr);
|
||||
#else
|
||||
m_display_window = new OpenGLDisplayWindow(this, nullptr);
|
||||
m_display_widget = new OpenGLDisplayWidget(this, nullptr);
|
||||
#endif
|
||||
connect(m_display_window, &QtDisplayWindow::windowResizedEvent, this, &QtHostInterface::onDisplayWindowResized);
|
||||
return m_display_window;
|
||||
connect(m_display_widget, &QtDisplayWidget::windowResizedEvent, this, &QtHostInterface::onDisplayWidgetResized);
|
||||
return m_display_widget;
|
||||
}
|
||||
|
||||
void QtHostInterface::bootSystem(const SystemBootParameters& params)
|
||||
|
@ -188,43 +189,43 @@ void QtHostInterface::handleKeyEvent(int key, bool 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
|
||||
if (m_display_window)
|
||||
m_display_window->WindowResized(width, height);
|
||||
if (m_display_widget)
|
||||
m_display_widget->windowResized(width, height);
|
||||
}
|
||||
|
||||
bool QtHostInterface::AcquireHostDisplay()
|
||||
{
|
||||
DebugAssert(!m_display_window);
|
||||
DebugAssert(!m_display_widget);
|
||||
|
||||
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();
|
||||
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_window = nullptr;
|
||||
m_display_widget->destroyDeviceContext();
|
||||
m_display_widget = nullptr;
|
||||
emit destroyDisplayWindowRequested();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_display = m_display_window->getHostDisplayInterface();
|
||||
m_display = m_display_widget->getHostDisplayInterface();
|
||||
return true;
|
||||
}
|
||||
|
||||
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_window->destroyDeviceContext();
|
||||
m_display_window = nullptr;
|
||||
m_display_widget->destroyDeviceContext();
|
||||
m_display_widget = nullptr;
|
||||
emit destroyDisplayWindowRequested();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include "core/host_interface.h"
|
||||
#include "core/system.h"
|
||||
#include "frontend-common/common_host_interface.h"
|
||||
#include "opengldisplaywindow.h"
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSettings>
|
||||
|
@ -24,6 +23,8 @@ class QTimer;
|
|||
|
||||
class GameList;
|
||||
|
||||
class QtDisplayWidget;
|
||||
|
||||
Q_DECLARE_METATYPE(SystemBootParameters);
|
||||
|
||||
class QtHostInterface : public QObject, private CommonHostInterface
|
||||
|
@ -51,7 +52,7 @@ public:
|
|||
|
||||
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);
|
||||
|
||||
|
@ -101,7 +102,7 @@ public Q_SLOTS:
|
|||
|
||||
private Q_SLOTS:
|
||||
void doStopThread();
|
||||
void onDisplayWindowResized(int width, int height);
|
||||
void onDisplayWidgetResized(int width, int height);
|
||||
void doBackgroundControllerPoll();
|
||||
|
||||
protected:
|
||||
|
@ -155,7 +156,7 @@ private:
|
|||
QSettings m_qsettings;
|
||||
std::mutex m_qsettings_mutex;
|
||||
|
||||
QtDisplayWindow* m_display_window = nullptr;
|
||||
QtDisplayWidget* m_display_widget = nullptr;
|
||||
QThread* m_original_thread = nullptr;
|
||||
Thread* m_worker_thread = nullptr;
|
||||
QEventLoop* m_worker_thread_event_loop = nullptr;
|
||||
|
|
|
@ -8,11 +8,11 @@
|
|||
#include <tuple>
|
||||
Log_SetChannel(OpenGLHostDisplay);
|
||||
|
||||
class OpenGLHostDisplayTexture : public HostDisplayTexture
|
||||
class OpenGLDisplayWidgetTexture : public HostDisplayTexture
|
||||
{
|
||||
public:
|
||||
OpenGLHostDisplayTexture(GLuint id, u32 width, u32 height) : m_id(id), m_width(width), m_height(height) {}
|
||||
~OpenGLHostDisplayTexture() override { glDeleteTextures(1, &m_id); }
|
||||
OpenGLDisplayWidgetTexture(GLuint id, u32 width, u32 height) : m_id(id), m_width(width), m_height(height) {}
|
||||
~OpenGLDisplayWidgetTexture() override { glDeleteTextures(1, &m_id); }
|
||||
|
||||
void* GetHandle() const override { return reinterpret_cast<void*>(static_cast<uintptr_t>(m_id)); }
|
||||
u32 GetWidth() const override { return m_width; }
|
||||
|
@ -20,7 +20,7 @@ public:
|
|||
|
||||
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)
|
||||
{
|
||||
GLuint id;
|
||||
|
@ -39,7 +39,7 @@ public:
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
return std::make_unique<OpenGLHostDisplayTexture>(id, width, height);
|
||||
return std::make_unique<OpenGLDisplayWidgetTexture>(id, width, height);
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
const void* data, u32 data_stride)
|
||||
{
|
||||
OpenGLHostDisplayTexture* tex = static_cast<OpenGLHostDisplayTexture*>(texture);
|
||||
OpenGLDisplayWidgetTexture* tex = static_cast<OpenGLDisplayWidgetTexture*>(texture);
|
||||
Assert(data_stride == (width * sizeof(u32)));
|
||||
|
||||
GLint old_texture_binding = 0;
|
||||
|
|
Loading…
Reference in a new issue