Qt: Replace QWindow for display with QWidget base

Not as elegant, but it solves the input focus issue.
This commit is contained in:
Connor McLaughlin 2020-03-12 13:53:51 +10:00
parent db1070a683
commit 2480624cbe
15 changed files with 449 additions and 375 deletions

View file

@ -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()

View file

@ -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;

View file

@ -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;

View file

@ -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" />

View file

@ -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" />

View file

@ -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()

View file

@ -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;

View file

@ -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, &current_fbo); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_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;

View file

@ -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;

View 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);
}
}

View file

@ -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;
}; };

View file

@ -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);
}

View file

@ -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();
} }

View file

@ -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;

View file

@ -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;