Skip to content

Commit

Permalink
imgui: use sdl2 backend
Browse files Browse the repository at this point in the history
  • Loading branch information
scribam committed Jan 11, 2024
1 parent 9f2fb96 commit 9c0b9d4
Show file tree
Hide file tree
Showing 17 changed files with 811 additions and 68 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,12 @@ if(NOT LIBRETRO)
core/deps/imgui/imgui_tables.cpp
core/deps/imgui/imgui_widgets.cpp)

if(SDL2_FOUND)
target_sources(${PROJECT_NAME} PRIVATE
core/deps/imgui/backends/imgui_impl_sdl2.cpp
core/deps/imgui/backends/imgui_impl_sdl2.h)
endif()

if(ENABLE_FC_PROFILER)
target_include_directories(${PROJECT_NAME} PRIVATE core/deps/implot)
target_sources(${PROJECT_NAME} PRIVATE
Expand Down
674 changes: 674 additions & 0 deletions core/deps/imgui/backends/imgui_impl_sdl2.cpp

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions core/deps/imgui/backends/imgui_impl_sdl2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// dear imgui: Platform Backend for SDL2
// This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..)
// (Info: SDL2 is a cross-platform general purpose library for handling windows, inputs, graphics context creation, etc.)

// Implemented features:
// [X] Platform: Clipboard support.
// [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen.
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [X] Platform: Basic IME support. App needs to call 'SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");' before SDL_CreateWindow()!.

// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// Learn about Dear ImGui:
// - FAQ https://dearimgui.com/faq
// - Getting Started https://dearimgui.com/getting-started
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
// - Introduction, links and more at the top of imgui.cpp

#pragma once
#include "imgui.h" // IMGUI_IMPL_API
#ifndef IMGUI_DISABLE

struct SDL_Window;
struct SDL_Renderer;
typedef union SDL_Event SDL_Event;

IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOpenGL(SDL_Window* window, void* sdl_gl_context);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForVulkan(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForD3D(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForMetal(SDL_Window* window);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForSDLRenderer(SDL_Window* window, SDL_Renderer* renderer);
IMGUI_IMPL_API bool ImGui_ImplSDL2_InitForOther(SDL_Window* window);
IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown();
IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame();
IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);

#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter
#endif

#endif // #ifndef IMGUI_DISABLE
6 changes: 5 additions & 1 deletion core/rend/dx11/dx11_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,27 @@
#pragma once
#include "rend/imgui_driver.h"
#include "imgui_impl_dx11.h"
#include "imgui_impl_sdl2.h"
#include "dx11context.h"
#include "rend/gui.h"
#include <unordered_map>

class DX11Driver final : public ImGuiDriver
{
public:
DX11Driver(ID3D11Device* device, ID3D11DeviceContext* deviceContext) {
DX11Driver(SDL_Window* window, ID3D11Device* device, ID3D11DeviceContext* deviceContext) {
ImGui_ImplSDL2_InitForD3D(window);
ImGui_ImplDX11_Init(device, deviceContext);
}

~DX11Driver() override {
ImGui_ImplDX11_Shutdown();
ImGui_ImplSDL2_Shutdown();
}

void newFrame() override {
ImGui_ImplDX11_NewFrame();
ImGui_ImplSDL2_NewFrame();
}

void renderDrawData(ImDrawData *drawData, bool gui_open) override {
Expand Down
27 changes: 17 additions & 10 deletions core/rend/dx11/dx11context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@
#include "dx11context.h"
#ifndef LIBRETRO
#include "rend/osd.h"
#ifdef USE_SDL
#include "sdl/sdl.h"
#endif
#include "hw/pvr/Renderer_if.h"
#include "emulator.h"
#include "dx11_driver.h"
#include "imgui_impl_dx11.h"
#include <dxgi.h>
#include <dxgi1_6.h>
#include <SDL_syswm.h>
#ifdef TARGET_UWP
#include <windows.h>
#include <gamingdeviceinformation.h>
Expand All @@ -41,10 +40,14 @@ bool DX11Context::init(bool keepCurrentWindow)
{
NOTICE_LOG(RENDERER, "DX11 Context initializing");
GraphicsContext::instance = this;
#ifdef USE_SDL

if (!keepCurrentWindow && !sdl_recreate_window(0))
return false;
#endif

SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(static_cast<SDL_Window*>(window), &wmInfo);

#ifdef TARGET_UWP
GAMING_DEVICE_MODEL_INFORMATION info {};
GetGamingDeviceModelInformation(&info);
Expand All @@ -57,6 +60,9 @@ bool DX11Context::init(bool keepCurrentWindow)
settings.display.height = displayMode->ResolutionHeightInRawPixels;
settings.display.uiScale = settings.display.width / 1920.0f * 1.4f;
}
IInspectable * coreWindow = wmInfo.info.winrt.window;
#else
HWND hwnd = wmInfo.info.win.window;
#endif

// Use high performance GPU on Windows 10 (1803 or later)
Expand Down Expand Up @@ -131,9 +137,9 @@ bool DX11Context::init(bool keepCurrentWindow)
#ifdef TARGET_UWP
desc.Width = settings.display.width;
desc.Height = settings.display.height;
hr = dxgiFactory2->CreateSwapChainForCoreWindow(pDevice, (IUnknown *)window, &desc, nullptr, &swapchain1.get());
hr = dxgiFactory2->CreateSwapChainForCoreWindow(pDevice, reinterpret_cast<IUnknown*>(coreWindow), &desc, nullptr, &swapchain1.get());
#else
hr = dxgiFactory2->CreateSwapChainForHwnd(pDevice, (HWND)window, &desc, nullptr, nullptr, &swapchain1.get());
hr = dxgiFactory2->CreateSwapChainForHwnd(pDevice, hwnd, &desc, nullptr, nullptr, &swapchain1.get());
#endif
if (SUCCEEDED(hr))
swapchain1.as(swapchain);
Expand All @@ -144,13 +150,13 @@ bool DX11Context::init(bool keepCurrentWindow)
swapchain1.reset();
#ifdef TARGET_UWP
return false;
#endif
#else
DXGI_SWAP_CHAIN_DESC desc{};
desc.BufferCount = 2;
desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.BufferDesc.RefreshRate.Numerator = 60;
desc.BufferDesc.RefreshRate.Denominator = 1;
desc.OutputWindow = (HWND)window;
desc.OutputWindow = hwnd;
desc.Windowed = TRUE;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.BufferCount = 2;
Expand All @@ -159,6 +165,7 @@ bool DX11Context::init(bool keepCurrentWindow)
desc.SampleDesc.Quality = 0;

hr = dxgiFactory->CreateSwapChain(pDevice, &desc, &swapchain.get());
#endif
}
if (FAILED(hr)) {
WARN_LOG(RENDERER, "D3D11 swap chain creation failed: %x", hr);
Expand All @@ -168,7 +175,7 @@ bool DX11Context::init(bool keepCurrentWindow)

#ifndef TARGET_UWP
// Prevent DXGI from monitoring our message queue for ALT+Enter
dxgiFactory->MakeWindowAssociation((HWND)window, DXGI_MWA_NO_WINDOW_CHANGES);
dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
#endif
D3D11_FEATURE_DATA_SHADER_CACHE cacheSupport{};
if (SUCCEEDED(pDevice->CheckFeatureSupport(D3D11_FEATURE_SHADER_CACHE, &cacheSupport, (UINT)sizeof(cacheSupport))))
Expand All @@ -178,7 +185,7 @@ bool DX11Context::init(bool keepCurrentWindow)
NOTICE_LOG(RENDERER, "No system-provided shader cache");
}

imguiDriver = std::unique_ptr<ImGuiDriver>(new DX11Driver(pDevice, pDeviceContext));
imguiDriver = std::make_unique<DX11Driver>(static_cast<SDL_Window*>(window), pDevice, pDeviceContext);
resize();
shaders.init(pDevice, &D3DCompile);
overlay.init(pDevice, pDeviceContext, &shaders, &samplers);
Expand Down
6 changes: 5 additions & 1 deletion core/rend/dx9/dx9_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,26 @@
#pragma once
#include "rend/imgui_driver.h"
#include "imgui_impl_dx9.h"
#include "imgui_impl_sdl2.h"
#include "dxcontext.h"
#include <unordered_map>

class DX9Driver final : public ImGuiDriver
{
public:
DX9Driver(IDirect3DDevice9* device) {
DX9Driver(SDL_Window* window, IDirect3DDevice9* device) {
ImGui_ImplSDL2_InitForD3D(window);
ImGui_ImplDX9_Init(device);
}

~DX9Driver() override {
ImGui_ImplDX9_Shutdown();
ImGui_ImplSDL2_Shutdown();
}

void newFrame() override {
ImGui_ImplDX9_NewFrame();
ImGui_ImplSDL2_NewFrame();
}

void renderDrawData(ImDrawData *drawData, bool gui_open) override {
Expand Down
16 changes: 10 additions & 6 deletions core/rend/dx9/dxcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,36 @@
#include "dxcontext.h"
#include "d3d_renderer.h"
#include "rend/osd.h"
#ifdef USE_SDL
#include "sdl/sdl.h"
#endif
#include "hw/pvr/Renderer_if.h"
#include "emulator.h"
#include "dx9_driver.h"
#include "imgui_impl_dx9.h"

#include <SDL_syswm.h>

DXContext theDXContext;

bool DXContext::init(bool keepCurrentWindow)
{
NOTICE_LOG(RENDERER, "DX9 Context initializing");
GraphicsContext::instance = this;
#ifdef USE_SDL

if (!keepCurrentWindow && !sdl_recreate_window(0))
return false;
#endif

SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(static_cast<SDL_Window*>(window), &wmInfo);
HWND hwnd = wmInfo.info.win.window;

pD3D.reset(Direct3DCreate9(D3D_SDK_VERSION));
if (!pD3D) {
ERROR_LOG(RENDERER, "Direct3DCreate9 failed");
return false;
}
memset(&d3dpp, 0, sizeof(d3dpp));
d3dpp.hDeviceWindow = (HWND)window;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Windowed = true;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
Expand Down Expand Up @@ -81,7 +85,7 @@ bool DXContext::init(bool keepCurrentWindow)
ERROR_LOG(RENDERER, "DirectX9 device creation failed: %x", hr);
return false;
}
imguiDriver = std::unique_ptr<ImGuiDriver>(new DX9Driver(pDevice));
imguiDriver = std::make_unique<DX9Driver>(static_cast<SDL_Window*>(window), pDevice);
overlay.init(pDevice);

D3DADAPTER_IDENTIFIER9 id;
Expand Down
14 changes: 13 additions & 1 deletion core/rend/gles/opengl_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include "rend/gui.h"
#include "glcache.h"
#include "gles.h"
#ifdef USE_SDL
#include "imgui_impl_sdl2.h"
#endif

#ifndef GL_CLAMP_TO_BORDER
#define GL_CLAMP_TO_BORDER 0x812D
Expand All @@ -45,10 +48,13 @@ constexpr int VMU_WIDTH = 70 * 48 / 32;
constexpr int VMU_HEIGHT = 70;
constexpr int VMU_PADDING = 8;

OpenGLDriver::OpenGLDriver()
OpenGLDriver::OpenGLDriver(void* window, void* sdl_gl_context)
{
for (auto& tex : vmu_lcd_tex_ids)
tex = ImTextureID();
#ifdef USE_SDL
ImGui_ImplSDL2_InitForOpenGL(static_cast<SDL_Window*>(window), sdl_gl_context);
#endif
ImGui_ImplOpenGL3_Init();
EventManager::listen(Event::Resume, emuEventCallback, this);
EventManager::listen(Event::Terminate, emuEventCallback, this);
Expand All @@ -71,6 +77,9 @@ OpenGLDriver::~OpenGLDriver()
if (!texIds.empty())
glcache.DeleteTextures(texIds.size(), &texIds[0]);
ImGui_ImplOpenGL3_Shutdown();
#ifdef USE_SDL
ImGui_ImplSDL2_Shutdown();
#endif
}

void OpenGLDriver::displayVmus()
Expand Down Expand Up @@ -156,6 +165,9 @@ void OpenGLDriver::displayCrosshairs()
void OpenGLDriver::newFrame()
{
ImGui_ImplOpenGL3_NewFrame();
#ifdef USE_SDL
ImGui_ImplSDL2_NewFrame();
#endif
}

void OpenGLDriver::renderDrawData(ImDrawData* drawData, bool gui_open)
Expand Down
2 changes: 1 addition & 1 deletion core/rend/gles/opengl_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
class OpenGLDriver final : public ImGuiDriver
{
public:
OpenGLDriver();
OpenGLDriver(void* window = nullptr, void* sdl_gl_context = nullptr);
~OpenGLDriver() override;

void displayVmus() override;
Expand Down
13 changes: 6 additions & 7 deletions core/rend/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,15 @@ void gui_init()
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
#if FC_PROFILER
ImPlot::CreateContext();
#endif
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls

io.IniFilename = NULL;
io.IniFilename = nullptr; // Disable automatic .ini loading/saving

io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
#if FC_PROFILER
ImPlot::CreateContext();
#endif

EventManager::listen(Event::Resume, emuEventCallback);
EventManager::listen(Event::Start, emuEventCallback);
Expand Down
7 changes: 6 additions & 1 deletion core/rend/vulkan/vulkan_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,12 @@ bool VulkanContext::InitInstance(const char** extensions, uint32_t extensions_co
void VulkanContext::InitImgui()
{
imguiDriver.reset();
imguiDriver = std::unique_ptr<ImGuiDriver>(new VulkanDriver());
imguiDriver = std::make_unique<VulkanDriver>();

#ifdef USE_SDL
ImGui_ImplSDL2_InitForVulkan(static_cast<SDL_Window*>(window));
#endif

ImGui_ImplVulkan_InitInfo initInfo{};
initInfo.Instance = (VkInstance)*instance;
initInfo.PhysicalDevice = (VkPhysicalDevice)physicalDevice;
Expand Down
11 changes: 10 additions & 1 deletion core/rend/vulkan/vulkan_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
*/
#pragma once
#include "rend/imgui_driver.h"
#ifdef USE_SDL
#include "imgui_impl_sdl2.h"
#endif
#include "imgui_impl_vulkan.h"
#include "vulkan_context.h"
#include "texture.h"
Expand All @@ -26,14 +29,20 @@
class VulkanDriver final : public ImGuiDriver
{
public:
~VulkanDriver() {
~VulkanDriver() override {
textures.clear();
linearSampler.reset();
ImGui_ImplVulkan_Shutdown();
#ifdef USE_SDL
ImGui_ImplSDL2_Shutdown();
#endif
}

void newFrame() override {
ImGui_ImplVulkan_NewFrame();
#ifdef USE_SDL
ImGui_ImplSDL2_NewFrame();
#endif
}

void renderDrawData(ImDrawData *drawData, bool gui_open) override
Expand Down
Loading

0 comments on commit 9c0b9d4

Please sign in to comment.