Skip to content

Commit

Permalink
imgui_app + CaptureTool: basic support for capturing from secondary v…
Browse files Browse the repository at this point in the history
…iewport. (#33)

Needed to retire IMGUI_APP_IMPLEMENTATION from imgui_app.cpp as it needs to access backend internals.
StitchAll still broken.
  • Loading branch information
ocornut committed Sep 28, 2023
1 parent 27d623e commit bba3329
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 18 deletions.
9 changes: 8 additions & 1 deletion imgui_test_engine/imgui_capture_tool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,14 @@ ImGuiCaptureStatus ImGuiCaptureContext::CaptureUpdate(ImGuiCaptureArgs* args)
else
IM_ASSERT(h == output->Height);

const ImGuiID viewport_id = 0;
ImGuiID viewport_id = 0;
#ifdef IMGUI_HAS_VIEWPORT
if (args->InFlags & ImGuiCaptureFlags_StitchAll)
viewport_id = _WindowsData[0].Window->ViewportId;
else
viewport_id = ImGui::GetMainViewport()->ID;
#endif

//printf("ScreenCaptureFunc x1: %d, y1: %d, w: %d, h: %d\n", x1, y1, w, h);
if (!ScreenCaptureFunc(viewport_id, x1, y1, w, h, &output->Data[_ChunkNo * w * capture_height], ScreenCaptureUserData))
{
Expand Down
3 changes: 0 additions & 3 deletions imgui_test_suite/imgui_test_suite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@
#include "imgui_test_engine/thirdparty/Str/Str.h"

// imgui_app (this is a helper to wrap multiple backends)
#ifndef IMGUI_APP_IMPLEMENTATION
#define IMGUI_APP_IMPLEMENTATION 1
#endif
#include "shared/imgui_app.h"

// ImPlot (optional for users of test engine, but we use it in test suite)
Expand Down
81 changes: 70 additions & 11 deletions shared/imgui_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@
*/
//-----------------------------------------------------------------------------

#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif

#ifndef IMGUI_APP_IMPLEMENTATION
#define IMGUI_APP_IMPLEMENTATION 1
#endif

#include "imgui_app.h"
#include "imgui.h"
Expand Down Expand Up @@ -77,7 +84,7 @@ Index of this file:

// Forward declarations
#if defined(IMGUI_APP_GL2) || defined(IMGUI_APP_GL3)
static bool ImGuiApp_ImplGL_CaptureFramebuffer(ImGuiApp* app, int x, int y, int w, int h, unsigned int* pixels, void* user_data);
static bool ImGuiApp_ImplGL_CaptureFramebuffer(ImGuiApp* app, ImGuiViewport* viewport, int x, int y, int w, int h, unsigned int* pixels, void* user_data);
#endif

// Linking
Expand All @@ -96,10 +103,16 @@ static bool ImGuiApp_ImplGL_CaptureFramebuffer(ImGuiApp* app, int x, int y, int
bool ImGuiApp_ScreenCaptureFunc(ImGuiID viewport_id, int x, int y, int w, int h, unsigned int* pixels, void* user_data)
{
ImGuiApp* app = (ImGuiApp*)user_data;
IM_UNUSED(viewport_id); // FIXME: Unsupported
if (app->CaptureFramebuffer == NULL)
return false;
return app->CaptureFramebuffer(app, x, y, w, h, pixels, NULL);
#ifdef IMGUI_HAS_VIEWPORT
ImGuiViewport* viewport = ImGui::FindViewportByID(viewport_id);
#else
ImGuiViewport* viewport = ImGui::GetMainViewport();
IM_UNUSED(viewport_id);
#endif
IM_ASSERT(viewport != NULL);
return app->CaptureFramebuffer(app, viewport, x, y, w, h, pixels, NULL);
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -171,8 +184,9 @@ static bool ImGuiApp_ImplNull_NewFrame(ImGuiApp* app_opaque)
return true;
}

static bool ImGuiApp_ImplNull_CaptureFramebuffer(ImGuiApp* app, int x, int y, int w, int h, unsigned int* pixels, void* user_data)
static bool ImGuiApp_ImplNull_CaptureFramebuffer(ImGuiApp* app, ImGuiViewport* viewport, int x, int y, int w, int h, unsigned int* pixels, void* user_data)
{
IM_UNUSED(viewport);
IM_UNUSED(app);
IM_UNUSED(user_data);
IM_UNUSED(x);
Expand Down Expand Up @@ -404,17 +418,30 @@ static void ImGuiApp_ImplWin32DX11_Render(ImGuiApp* app_opaque)
app->pSwapChain->Present(0, 0);
}

static bool ImGuiApp_ImplWin32DX11_CaptureFramebuffer(ImGuiApp* app_opaque, int x, int y, int w, int h, unsigned int* pixels_rgba, void* user_data)
static bool ImGuiApp_ImplWin32DX11_CaptureFramebuffer(ImGuiApp* app_opaque, ImGuiViewport* viewport, int x, int y, int w, int h, unsigned int* pixels_rgba, void* user_data)
{
IM_UNUSED(user_data);
ImGuiApp_ImplWin32DX11* app = (ImGuiApp_ImplWin32DX11*)app_opaque;
ImGuiContext& g = *GImGui;
ImGuiIO& io = g.IO;

ID3D11RenderTargetView* rtView = app->mainRenderTargetView;
UINT rtWidth = (UINT)io.DisplaySize.x;
UINT rtHeight = (UINT)io.DisplaySize.y;
#ifdef IMGUI_HAS_VIEWPORT
if (viewport != NULL)
if (ImGui_ImplDX11_ViewportData* vd = (ImGui_ImplDX11_ViewportData*)viewport->RendererUserData)
{
rtView = vd->RTView;
rtWidth = (UINT)viewport->Size.x;
rtHeight = (UINT)viewport->Size.y;
}
#endif

D3D11_TEXTURE2D_DESC texture_desc;
memset(&texture_desc, 0, sizeof(texture_desc));
texture_desc.Width = (UINT)io.DisplaySize.x;
texture_desc.Height = (UINT)io.DisplaySize.y;
texture_desc.Width = rtWidth;
texture_desc.Height = rtHeight;
texture_desc.MipLevels = 1;
texture_desc.ArraySize = 1;
texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
Expand All @@ -436,7 +463,7 @@ static bool ImGuiApp_ImplWin32DX11_CaptureFramebuffer(ImGuiApp* app_opaque, int
}

ID3D11Resource* source = NULL;
app->mainRenderTargetView->GetResource(&source);
rtView->GetResource(&source);
app->pd3dDeviceContext->CopyResource(texture, source);
source->Release();

Expand Down Expand Up @@ -593,6 +620,7 @@ static LRESULT WINAPI ImGuiApp_ImplWin32_WndProc(HWND hWnd, UINT msg, WPARAM wPa
//-----------------------------------------------------------------------------

#ifdef IMGUI_APP_GL3
#ifndef IMGUI_APP_IMPLEMENTATION
#include "imgui_impl_opengl3.h"

// GL includes
Expand All @@ -607,6 +635,7 @@ static LRESULT WINAPI ImGuiApp_ImplWin32_WndProc(HWND hWnd, UINT msg, WPARAM wPa
#else
#include "imgui_impl_opengl3_loader.h"
#endif
#endif

#endif

Expand Down Expand Up @@ -754,6 +783,16 @@ static void ImGuiApp_ImplSdlGL2_ShutdownBackends(ImGuiApp* app_opaque)
ImGui_ImplSDL2_Shutdown();
}

static bool ImGuiApp_ImplSdlGL2_CaptureFramebuffer(ImGuiApp* app, ImGuiViewport* viewport, int x, int y, int w, int h, unsigned int* pixels, void* user_data)
{
#ifdef IMGUI_HAS_VIEWPORT
if (ImGui_ImplSDL2_ViewportData* vd = (ImGui_ImplSDL2_ViewportData*)viewport->PlatformUserData)
if (vd->GLContext)
SDL_GL_MakeCurrent(vd->Window, vd->GLContext);
#endif
return ImGuiApp_ImplGL_CaptureFramebuffer(app, viewport, x, y, w, h, pixels, user_data);
}

ImGuiApp* ImGuiApp_ImplSdlGL2_Create()
{
ImGuiApp_ImplSdlGLX* intf = new ImGuiApp_ImplSdlGLX();
Expand All @@ -763,7 +802,7 @@ ImGuiApp* ImGuiApp_ImplSdlGL2_Create()
intf->Render = ImGuiApp_ImplSdlGL2_Render;
intf->ShutdownCloseWindow = ImGuiApp_ImplSdlGLX_ShutdownCloseWindow;
intf->ShutdownBackends = ImGuiApp_ImplSdlGL2_ShutdownBackends;
intf->CaptureFramebuffer = ImGuiApp_ImplGL_CaptureFramebuffer;
intf->CaptureFramebuffer = ImGuiApp_ImplSdlGL2_CaptureFramebuffer;
intf->Destroy = [](ImGuiApp* app) { SDL_Quit(); delete (ImGuiApp_ImplSdlGLX*)app; };
return intf;
}
Expand Down Expand Up @@ -895,6 +934,16 @@ static void ImGuiApp_ImplSdlGL3_ShutdownBackends(ImGuiApp* app_opaque)
ImGui_ImplSDL2_Shutdown();
}

static bool ImGuiApp_ImplSdlGL3_CaptureFramebuffer(ImGuiApp* app, ImGuiViewport* viewport, int x, int y, int w, int h, unsigned int* pixels, void* user_data)
{
#ifdef IMGUI_HAS_VIEWPORT
if (ImGui_ImplSDL2_ViewportData* vd = (ImGui_ImplSDL2_ViewportData*)viewport->PlatformUserData)
if (vd->GLContext)
SDL_GL_MakeCurrent(vd->Window, vd->GLContext);
#endif
return ImGuiApp_ImplGL_CaptureFramebuffer(app, viewport, x, y, w, h, pixels, user_data);
}

ImGuiApp* ImGuiApp_ImplSdlGL3_Create()
{
ImGuiApp_ImplSdlGLX* intf = new ImGuiApp_ImplSdlGLX();
Expand All @@ -904,7 +953,7 @@ ImGuiApp* ImGuiApp_ImplSdlGL3_Create()
intf->Render = ImGuiApp_ImplSdlGL3_Render;
intf->ShutdownCloseWindow = ImGuiApp_ImplSdlGLX_ShutdownCloseWindow;
intf->ShutdownBackends = ImGuiApp_ImplSdlGL3_ShutdownBackends;
intf->CaptureFramebuffer = ImGuiApp_ImplGL_CaptureFramebuffer;
intf->CaptureFramebuffer = ImGuiApp_ImplSdlGL3_CaptureFramebuffer;
intf->Destroy = [](ImGuiApp* app) { SDL_Quit(); delete (ImGuiApp_ImplSdlGLX*)app; };
return intf;
}
Expand Down Expand Up @@ -1096,6 +1145,16 @@ static void ImGuiApp_ImplGlfwGL3_ShutdownBackends(ImGuiApp* app_opaque)
ImGui_ImplGlfw_Shutdown();
}

static bool ImGuiApp_ImplGlfwGL3_CaptureFramebuffer(ImGuiApp* app, ImGuiViewport* viewport, int x, int y, int w, int h, unsigned int* pixels, void* user_data)
{
#ifdef IMGUI_HAS_VIEWPORT
if (ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData)
if (vd->Window)
glfwMakeContextCurrent(vd->Window);
#endif
return ImGuiApp_ImplGL_CaptureFramebuffer(app, viewport, x, y, w, h, pixels, user_data);
}

ImGuiApp* ImGuiApp_ImplGlfwGL3_Create()
{
ImGuiApp_ImplGlfwGL3* intf = new ImGuiApp_ImplGlfwGL3();
Expand All @@ -1117,7 +1176,7 @@ ImGuiApp* ImGuiApp_ImplGlfwGL3_Create()
//-----------------------------------------------------------------------------

#if defined(IMGUI_APP_GL2) || defined(IMGUI_APP_GL3)
static bool ImGuiApp_ImplGL_CaptureFramebuffer(ImGuiApp* app, int x, int y, int w, int h, unsigned int* pixels, void* user_data)
static bool ImGuiApp_ImplGL_CaptureFramebuffer(ImGuiApp* app, ImGuiViewport* viewport, int x, int y, int w, int h, unsigned int* pixels, void* user_data)
{
IM_UNUSED(app);
IM_UNUSED(user_data);
Expand Down
5 changes: 2 additions & 3 deletions shared/imgui_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
// #define IMGUI_APP_SDL_GL3
// #define IMGUI_APP_GLFW_GL3
//-----------------------------------------------------------------------------
// To automatically include the backends .cpp, define in exactly one of your source file:
// #define IMGUI_APP_IMPLEMENTATION 1
// IMPORTANT: BACKENDS IMPLEMENTATIONS ARE AUTOMATICALLY LINKED IN imgui_app.cpp
//-----------------------------------------------------------------------------

#pragma once
Expand Down Expand Up @@ -39,7 +38,7 @@ struct ImGuiApp
void (*ShutdownCloseWindow)(ImGuiApp* app) = nullptr;
void (*ShutdownBackends)(ImGuiApp* app) = nullptr;
void (*Destroy)(ImGuiApp* app) = nullptr;
bool (*CaptureFramebuffer)(ImGuiApp* app, int x, int y, int w, int h, unsigned int* pixels_rgba, void* user_data) = nullptr;
bool (*CaptureFramebuffer)(ImGuiApp* app, ImGuiViewport* viewport, int x, int y, int w, int h, unsigned int* pixels_rgba, void* user_data) = nullptr;
};

// Helper stub to store directly in ImGuiTestEngineIO::ScreenCaptureFunc when using test engine (prototype is same as ImGuiScreenCaptureFunc)
Expand Down

0 comments on commit bba3329

Please sign in to comment.