Extract main toolbar and thin startup/node helpers

This commit is contained in:
2026-06-16 12:33:36 +02:00
parent acd34540e0
commit 184f662493
7 changed files with 507 additions and 320 deletions

View File

@@ -112,6 +112,239 @@ void drain_main_tasks()
}
}
struct MainWindowStartupState
{
WNDCLASS window_class{};
PIXELFORMATDESCRIPTOR pixel_format{};
DWORD window_style = WS_OVERLAPPEDWINDOW;
RECT client_rect{ 0, 0, 0, 0 };
POINT client_pos{ CW_USEDEFAULT, CW_USEDEFAULT };
int show_command = SW_NORMAL;
};
struct OpenGlWindowContext
{
HDC device_context{};
HGLRC render_context{};
pp::renderer::gl::OpenGlRuntimeInfo runtime_info{};
};
enum class MainStartupResult
{
Ok = 0,
GladLoadFailure = 1,
MissingCoreContextSupport = 2,
};
void ensure_runtime_data_directory()
{
FILE* fp_check = fopen("data\\layout.xml", "rb");
if (!fp_check)
{
LOG("data files not found");
static char path[MAX_PATH];
GetModuleFileNameA(NULL, path, MAX_PATH);
LOG("current dir %s", path);
PathRemoveFileSpecA(path);
SetCurrentDirectoryA(path);
LOG("change dir to %s", path);
return;
}
fclose(fp_check);
LOG("data files ok");
}
MainWindowStartupState initialize_main_window_startup_state()
{
auto& state = retained_state();
auto startup = MainWindowStartupState {};
state.hInst = GetModuleHandle(NULL);
state.className = L"EngineMain";
startup.window_class.hInstance = state.hInst;
startup.window_class.lpfnWndProc = (WNDPROC)WndProc;
startup.window_class.lpszClassName = state.className;
startup.window_class.hbrBackground = (HBRUSH)COLOR_WINDOW;
startup.window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClass(&startup.window_class);
auto monitor = MonitorFromWindow(0, MONITOR_DEFAULTTOPRIMARY);
auto x = unsigned{ 96 };
auto y = unsigned{ 96 };
if (GetDpiForMonitor_fn)
GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI, &x, &y);
App::I->display_density = (float)x / 96.f;
const auto window_preferences = pp::panopainter::read_legacy_window_preferences(SW_NORMAL);
if (window_preferences.has_ui_scale)
App::I->zoom = window_preferences.ui_scale;
else
App::I->zoom = (float)x / 96.f;
startup.show_command = window_preferences.show_command;
startup.client_rect = {
0,
0,
static_cast<LONG>(App::I->width * App::I->zoom),
static_cast<LONG>(App::I->height * App::I->zoom),
};
if (window_preferences.has_window_rect)
{
auto wnd_rect = window_preferences.window_rect;
App::I->width = wnd_rect.z - wnd_rect.x;
App::I->height = wnd_rect.w - wnd_rect.y;
startup.client_rect = { wnd_rect.x, wnd_rect.y, wnd_rect.z, wnd_rect.w };
startup.client_pos = { wnd_rect.x, wnd_rect.y };
}
else
{
AdjustWindowRect(&startup.client_rect, startup.window_style, false);
}
return startup;
}
void create_main_window(const MainWindowStartupState& startup, const wchar_t* window_title)
{
auto& state = retained_state();
const int window_width = startup.client_rect.right - startup.client_rect.left;
const int window_height = startup.client_rect.bottom - startup.client_rect.top;
state.hWnd = CreateWindow(
startup.window_class.lpszClassName,
window_title,
startup.window_style,
startup.client_pos.x,
startup.client_pos.y,
window_width,
window_height,
0,
0,
state.hInst,
0);
}
void initialize_pixel_format_descriptor(PIXELFORMATDESCRIPTOR& pixel_format)
{
pixel_format.nSize = sizeof(pixel_format);
pixel_format.nVersion = 1;
pixel_format.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pixel_format.iPixelType = PFD_TYPE_RGBA;
pixel_format.cColorBits = 32;
pixel_format.cDepthBits = 24;
pixel_format.iLayerType = PFD_MAIN_PLANE;
}
bool load_glad_entry_points(HDC device_context)
{
if (!gladLoadGL())
{
LOG("gladLoadGL() failed");
return false;
}
if (!gladLoadWGL(device_context))
{
LOG("gladLoadWGL() failed");
return false;
}
return true;
}
pp::renderer::gl::OpenGlRuntimeInfo log_runtime_info()
{
auto runtime_info = pp::renderer::gl::OpenGlRuntimeInfo {};
const auto runtime_info_result = pp::renderer::gl::query_opengl_runtime_info(
pp::legacy::gl_runtime::runtime_info_dispatch());
if (runtime_info_result.ok())
{
runtime_info = runtime_info_result.value();
LOG("GL version: %s", runtime_info.version);
LOG("GL vendor: %s", runtime_info.vendor);
LOG("GL renderer: %s", runtime_info.renderer);
}
else
{
LOG("OpenGL runtime info query failed: %s", runtime_info_result.status().message);
}
return runtime_info;
}
bool upgrade_to_core_gl_context(const MainWindowStartupState& startup, OpenGlWindowContext& context)
{
if (!GLAD_WGL_ARB_create_context)
{
LOG("WGL_ARB_create_context not supported");
// If not supported, go fuck yourself we are not gonna support your shitty device
return false;
}
const auto wgl_config = pp::renderer::gl::windows_wgl_core_context_3_3_config();
UINT num_format = 0;
wglMakeCurrent(NULL, NULL);
wglDeleteContext(context.render_context);
DestroyWindow(retained_state().hWnd);
create_main_window(startup, retained_state().window_title);
context.device_context = GetDC(retained_state().hWnd);
int pixel_format = 0;
wglChoosePixelFormatARB(
context.device_context,
wgl_config.pixel_format_attributes.data(),
nullptr,
1,
&pixel_format,
&num_format);
SetPixelFormat(context.device_context, pixel_format, &startup.pixel_format);
context.render_context = wglCreateContextAttribsARB(
context.device_context,
NULL,
wgl_config.context_attributes.data());
wglMakeCurrent(context.device_context, context.render_context);
pp::platform::windows::set_async_render_context(context.device_context, context.render_context);
return true;
}
MainStartupResult initialize_main_window_and_gl(MainWindowStartupState& startup, OpenGlWindowContext& context)
{
create_main_window(startup, L"PanoPainter");
initialize_pixel_format_descriptor(startup.pixel_format);
context.device_context = GetDC(retained_state().hWnd);
const int pixel_format = ChoosePixelFormat(context.device_context, &startup.pixel_format);
SetPixelFormat(context.device_context, pixel_format, &startup.pixel_format);
context.render_context = wglCreateContext(context.device_context);
wglMakeCurrent(context.device_context, context.render_context);
pp::platform::windows::set_async_render_context(context.device_context, context.render_context);
if (!load_glad_entry_points(context.device_context))
return MainStartupResult::GladLoadFailure;
context.runtime_info = log_runtime_info();
#ifdef USE_RENDERDOC
if (!win32_renderdoc_init())
LOG("Renderdoc not started");
#endif
const auto renderer_name = std::string(context.runtime_info.renderer != nullptr ? context.runtime_info.renderer : "");
swprintf_s(
retained_state().window_title,
L"PanoPainter %s (%s)",
g_version_number_w,
str2wstr(renderer_name).c_str());
if (!upgrade_to_core_gl_context(startup, context))
return MainStartupResult::MissingCoreContextSupport;
return MainStartupResult::Ok;
}
}
HWND pp_windows_main_window_handle()
@@ -454,8 +687,6 @@ void win32_save_window_state()
int main(int argc, char** argv)
{
auto& state = retained_state();
WNDCLASS wc;
PIXELFORMATDESCRIPTOR pfd;
App::I = new App();
App::I->set_platform_services(&pp::platform::windows::platform_services());
@@ -467,23 +698,7 @@ int main(int argc, char** argv)
if(SetProcessDpiAwareness_fn)
SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE);
FILE* fp_check = fopen("data\\layout.xml", "rb");
if (!fp_check)
{
LOG("data files not found");
static char path[MAX_PATH];
GetModuleFileNameA(NULL, path, MAX_PATH);
LOG("current dir %s", path);
PathRemoveFileSpecA(path);
SetCurrentDirectoryA(path);
LOG("change dir to %s", path);
}
else
{
fclose(fp_check);
LOG("data files ok");
}
ensure_runtime_data_directory();
pp::platform::windows::SplashScreen splash(GetModuleHandle(NULL));
@@ -496,135 +711,17 @@ int main(int argc, char** argv)
App::I->create();
// Inizialize data structures to zero
memset(&wc, 0, sizeof(wc));
memset(&state.keys, 0, sizeof(state.keys));
memset(&pfd, 0, sizeof(pfd));
// Create the main window
state.hInst = GetModuleHandle(NULL);
state.className = L"EngineMain";
wc.hInstance = state.hInst;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.lpszClassName = state.className;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClass(&wc);
auto monitor = MonitorFromWindow(0, MONITOR_DEFAULTTOPRIMARY);
auto x = unsigned{ 96 };
auto y = unsigned{ 96 };
if (GetDpiForMonitor_fn)
GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI, &x, &y);
App::I->display_density = (float)x / 96.f;
const auto window_preferences = pp::panopainter::read_legacy_window_preferences(SW_NORMAL);
if (window_preferences.has_ui_scale)
App::I->zoom = window_preferences.ui_scale;
else
App::I->zoom = (float)x / 96.f;
int show_cmd = window_preferences.show_command;
DWORD wnd_style = WS_OVERLAPPEDWINDOW;
//if (show_cmd == SW_MAXIMIZE)
// wnd_style != WS_MAXIMIZE;
RECT clientRect = { 0, 0, (int)App::I->width * App::I->zoom, (int)App::I->height * App::I->zoom };
POINT clientPos = { CW_USEDEFAULT, CW_USEDEFAULT };
if (window_preferences.has_window_rect)
auto startup = initialize_main_window_startup_state();
auto context = OpenGlWindowContext {};
switch (initialize_main_window_and_gl(startup, context))
{
auto wnd_rect = window_preferences.window_rect;
App::I->width = wnd_rect.z - wnd_rect.x;
App::I->height = wnd_rect.w - wnd_rect.y;
clientRect = { wnd_rect.x, wnd_rect.y, wnd_rect.z, wnd_rect.w };
clientPos = { wnd_rect.x, wnd_rect.y };
}
else
{
AdjustWindowRect(&clientRect, wnd_style, false);
}
state.hWnd = CreateWindow(wc.lpszClassName, L"PanoPainter", wnd_style, clientPos.x, clientPos.y,
(float)(clientRect.right - clientRect.left),
(float)(clientRect.bottom - clientRect.top), 0, 0, state.hInst, 0);
// Setup GL Rendering Context
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.iLayerType = PFD_MAIN_PLANE;
HDC hDC = GetDC(state.hWnd);
int pxfmt = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, pxfmt, &pfd);
HGLRC hRC = wglCreateContext(hDC); // Create OpenGL 2.1 or less
wglMakeCurrent(hDC, hRC);
pp::platform::windows::set_async_render_context(hDC, hRC);
// Initialize extensions
if (!gladLoadGL())
{
LOG("gladLoadGL() failed");
case MainStartupResult::Ok:
break;
case MainStartupResult::GladLoadFailure:
return 0;
}
if (!gladLoadWGL(hDC))
{
LOG("gladLoadWGL() failed");
return 0;
}
auto runtime_info = pp::renderer::gl::OpenGlRuntimeInfo {};
const auto runtime_info_result = pp::renderer::gl::query_opengl_runtime_info(
pp::legacy::gl_runtime::runtime_info_dispatch());
if (runtime_info_result.ok()) {
runtime_info = runtime_info_result.value();
LOG("GL version: %s", runtime_info.version);
LOG("GL vendor: %s", runtime_info.vendor);
LOG("GL renderer: %s", runtime_info.renderer);
} else {
LOG("OpenGL runtime info query failed: %s", runtime_info_result.status().message);
}
#ifdef USE_RENDERDOC
if (!win32_renderdoc_init())
LOG("Renderdoc not started");
#endif // USE_RENDERDOC
const auto renderer_name = std::string(runtime_info.renderer != nullptr ? runtime_info.renderer : "");
swprintf_s(state.window_title, L"PanoPainter %s (%s)", g_version_number_w,
str2wstr(renderer_name).c_str());
// If supported create a 3.3 context
if (GLAD_WGL_ARB_create_context)
{
const auto wgl_config = pp::renderer::gl::windows_wgl_core_context_3_3_config();
UINT numFormat;
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
DestroyWindow(state.hWnd);
state.hWnd = CreateWindow(wc.lpszClassName, state.window_title, wnd_style, clientPos.x, clientPos.y,
(float)(clientRect.right - clientRect.left),
(float)(clientRect.bottom - clientRect.top), 0, 0, state.hInst, 0);
hDC = GetDC(state.hWnd);
wglChoosePixelFormatARB(hDC, wgl_config.pixel_format_attributes.data(), nullptr, 1, &pxfmt, &numFormat);
SetPixelFormat(hDC, pxfmt, &pfd);
hRC = wglCreateContextAttribsARB(hDC, NULL, wgl_config.context_attributes.data());
wglMakeCurrent(hDC, hRC);
pp::platform::windows::set_async_render_context(hDC, hRC);
}
else
{
LOG("WGL_ARB_create_context not supported");
// If not supported, go fuck yourself we are not gonna support your shitty device
return -1; // A negative number because you are a negative one
case MainStartupResult::MissingCoreContextSupport:
return -1;
}
//wglSwapIntervalEXT(1);
@@ -682,7 +779,7 @@ int main(int argc, char** argv)
{
WINDOWPLACEMENT wp;
GetWindowPlacement(state.hWnd, &wp);
wp.showCmd = show_cmd;
wp.showCmd = startup.show_command;
SetWindowPlacement(state.hWnd, &wp);
//GetClientRect(hWnd, &clientRect);
//App::I->width = clientRect.right - clientRect.left;
@@ -721,7 +818,7 @@ int main(int argc, char** argv)
// Clean up
WacomTablet::I.terminate();
UnregisterClass(state.className, state.hInst);
UnregisterClass(startup.window_class.lpszClassName, state.hInst);
LogRemote::I.stop();
}