Skip to content

Commit 9bf008f

Browse files
authored
Add minimal window diagnostics
Add minimal module-only window example and GLFW error diagnostics.
1 parent 03d5960 commit 9bf008f

9 files changed

Lines changed: 202 additions & 5 deletions

File tree

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# imgui-m: GL Runtime Boundary Plan
2+
3+
> 状态: active
4+
> 分支: `codex/gl-runtime-closure-imgui`
5+
> PR: pending
6+
> Last updated: 2026-06-03
7+
> 目标: 保持 ImGui module wrapper 简洁,提供可诊断的最小窗口示例,并明确 GL runtime 由 mcpp/mcpp-index 层闭合。
8+
9+
## Scope
10+
11+
This repository owns the ImGui module wrapper and examples. It should prove
12+
that consumers can write a minimal window application with module imports, but
13+
it should not package platform OpenGL/GLX/EGL drivers.
14+
15+
## Current Work
16+
17+
- `examples/minimal_window/` demonstrates a module-only consumer path.
18+
- GLFW error forwarding lets examples report the actual window creation
19+
failure instead of silently exiting.
20+
- README and architecture docs explain that `compat.opengl` provides headers
21+
and registry data, not platform GL runtime libraries.
22+
23+
## Implementation Plan
24+
25+
- [x] Create this repository-level plan checkpoint.
26+
- [x] Add a minimal module-only window example.
27+
- [x] Add GLFW error accessors for backend diagnostics.
28+
- [x] Add test coverage for exported diagnostic API presence.
29+
- [x] Adjust the minimal example to capture GLFW error details before cleanup
30+
when a cleanup call could clear the last error.
31+
- [x] Keep README and architecture docs aligned with the final mcpp-index
32+
package names.
33+
- If the runtime provider lands as `compat.glvnd`, use that name.
34+
- If the package name changes during implementation, update docs only after
35+
the index PR settles.
36+
- [x] Add or update CI build-checks for `examples/minimal_window`.
37+
- Runtime execution should stay conditional on a visible display and OpenGL
38+
runtime.
39+
40+
## Non-Goals
41+
42+
- Do not bundle `libGL`, GLX/EGL, Mesa, NVIDIA, or host GPU driver files here.
43+
- Do not hard-code host library paths in example source.
44+
- Do not make headless CI depend on a real display.
45+
- Do not change `compat.opengl` semantics from this repository.
46+
47+
## Verification
48+
49+
- [x] `mcpp build`
50+
- [x] `mcpp test`
51+
- [x] `cd examples/basic && mcpp run`
52+
- [x] `cd examples/minimal_window && mcpp build`
53+
- [x] `cd examples/glfw_opengl3 && mcpp build`
54+
- [ ] On a machine with working display/runtime closure:
55+
`cd examples/minimal_window && mcpp run`
56+
57+
## PR / CI / Merge Notes
58+
59+
- [x] Commit this plan as the first checkpoint on the feature branch.
60+
- [ ] Keep current implementation checkpoint commits small.
61+
- [ ] Open a PR with sanitized paths and no local machine details.
62+
- [ ] Include a test plan that separates build-only CI from display-required
63+
runtime checks.
64+
- [ ] Wait for CI.
65+
- [ ] Squash merge after required checks pass.
66+
67+
## Cross-Repository Dependencies
68+
69+
- `mcpp` must implement runtime metadata/run environment support before the
70+
minimal window example can be expected to run without manual environment
71+
setup.
72+
- `mcpp-index` must express GLFW/OpenGL runtime requirements through package
73+
metadata.
74+
- `xim-pkgindex` is not required for this repository PR unless a released mcpp
75+
version becomes a package-index dependency.

.github/workflows/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ jobs:
4848
cd examples/basic
4949
mcpp run
5050
51+
- name: Build minimal window example
52+
run: |
53+
cd examples/minimal_window
54+
mcpp build
55+
5156
- name: Build GLFW/OpenGL3 example
5257
run: |
5358
cd examples/glfw_opengl3

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,22 @@ Dear ImGui 1.92.8 module frame ok
4545

4646
## Backend Example
4747

48-
The GLFW/OpenGL3 example builds on CI but should be run only in an environment
49-
with a working display and OpenGL context:
48+
The minimal GLFW/OpenGL3 window example uses the combined backend module and
49+
does not use `#include` in consumer code:
50+
51+
```bash
52+
cd examples/minimal_window
53+
mcpp build
54+
mcpp run
55+
```
56+
57+
It requires an OpenGL runtime that is visible to the mcpp/xlings runtime. If
58+
GLFW cannot create the window, the example prints the GLFW error text. The
59+
`compat.opengl` package supplies OpenGL registry/header content; it does not
60+
bundle a platform `libGL`/GLX runtime.
61+
62+
The larger GLFW/OpenGL3 example builds on CI but should be run only in an
63+
environment with a working display and OpenGL context:
5064

5165
```bash
5266
cd examples/glfw_opengl3
@@ -94,6 +108,7 @@ The `0.0.1` release state is verified with mcpp `0.0.44`:
94108
- `mcpp build`
95109
- `mcpp test`
96110
- `cd examples/basic && mcpp run`
111+
- `cd examples/minimal_window && mcpp build`
97112
- `cd examples/glfw_opengl3 && mcpp build`
98113

99114
## License

docs/architecture.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ upstream source ownership in compat packages.
3434
| `-- backend_test.cpp
3535
`-- examples/
3636
|-- basic/
37+
|-- minimal_window/
3738
`-- glfw_opengl3/
3839
```
3940

@@ -81,9 +82,10 @@ Primary proof points:
8182
mcpp build
8283
mcpp test
8384
cd examples/basic && mcpp run
85+
cd ../minimal_window && mcpp build
8486
cd ../glfw_opengl3 && mcpp build
8587
```
8688

87-
The GLFW/OpenGL3 example is a real windowed example. It is build-checked in
88-
headless CI and intended to be run on a machine with a working display/OpenGL
89-
context.
89+
The minimal and full GLFW/OpenGL3 examples are real windowed examples. They are
90+
build-checked in headless CI and intended to be run on a machine with a working
91+
display/OpenGL context.

examples/minimal_window/mcpp.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "imgui-minimal-window"
3+
version = "0.1.0"
4+
description = "Minimal GLFW/OpenGL3 window using imgui modules"
5+
license = "MIT"
6+
7+
[toolchain]
8+
linux = "llvm@20.1.7"
9+
10+
[dependencies]
11+
imgui = { path = "../.." }
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import std;
2+
import imgui.backend.glfw_opengl3;
3+
4+
namespace {
5+
struct GlfwError {
6+
int code = 0;
7+
const char* description = nullptr;
8+
};
9+
10+
GlfwError captureError() {
11+
const char* description = nullptr;
12+
const int errorCode = ImGui::Backend::GlfwOpenGL3::GetError(&description);
13+
return GlfwError{errorCode, description};
14+
}
15+
16+
int fail(const char* step, int exitCode, GlfwError error) {
17+
std::println(
18+
"failed at {}: GLFW error {} ({})",
19+
step,
20+
error.code,
21+
error.description != nullptr ? error.description : "no GLFW error description"
22+
);
23+
return exitCode;
24+
}
25+
}
26+
27+
int main() {
28+
namespace Backend = ImGui::Backend::GlfwOpenGL3;
29+
30+
if (!Backend::InitGlfw()) {
31+
return fail("glfwInit", 1, captureError());
32+
}
33+
34+
Backend::DefaultWindowHints();
35+
Backend::ConfigureOpenGL(3, 3, true, false);
36+
37+
auto* window = Backend::CreateWindow(640, 360, "mcpp imgui minimal window");
38+
if (window == nullptr) {
39+
const auto error = captureError();
40+
Backend::TerminateGlfw();
41+
return fail("glfwCreateWindow", 2, error);
42+
}
43+
44+
Backend::MakeContextCurrent(window);
45+
Backend::SwapInterval(1);
46+
47+
ImGuiContext* context = ImGui::CreateContext();
48+
ImGui::SetCurrentContext(context);
49+
50+
if (!Backend::Init(window)) {
51+
const auto error = captureError();
52+
ImGui::DestroyContext(context);
53+
Backend::DestroyWindow(window);
54+
Backend::TerminateGlfw();
55+
return fail("ImGui GLFW/OpenGL3 backend init", 3, error);
56+
}
57+
58+
while (!Backend::WindowShouldClose(window)) {
59+
Backend::PollEvents();
60+
Backend::NewFrame();
61+
62+
ImGui::NewFrame();
63+
ImGui::Begin("Minimal ImGui Window");
64+
ImGui::TextUnformatted("mcpp module import, no include in consumer code");
65+
ImGui::End();
66+
ImGui::Render();
67+
68+
Backend::RenderDrawData(ImGui::GetDrawData());
69+
Backend::SwapBuffers(window);
70+
}
71+
72+
Backend::Shutdown();
73+
ImGui::DestroyContext(context);
74+
Backend::DestroyWindow(window);
75+
Backend::TerminateGlfw();
76+
return 0;
77+
}

src/backends/glfw.cppm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export namespace ImGui::Backend::Glfw {
2424
return glfwGetVersionString();
2525
}
2626

27+
int GetError(const char** description) {
28+
return glfwGetError(description);
29+
}
30+
2731
void DefaultWindowHints() {
2832
glfwDefaultWindowHints();
2933
}

src/backends/glfw_opengl3.cppm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export namespace ImGui::Backend::GlfwOpenGL3 {
2020
return Glfw::GlfwVersionString();
2121
}
2222

23+
int GetError(const char** description) {
24+
return Glfw::GetError(description);
25+
}
26+
2327
void DefaultWindowHints() {
2428
Glfw::DefaultWindowHints();
2529
}

tests/backend_test.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ TEST(ImGuiGlfwBackendModuleTest, ExposesPlatformApi) {
1616
auto restoreCallbacks = &ImGui::Backend::Glfw::RestoreCallbacks;
1717
auto getContentScaleForWindow = &ImGui::Backend::Glfw::GetContentScaleForWindow;
1818
auto getContentScaleForMonitor = &ImGui::Backend::Glfw::GetContentScaleForMonitor;
19+
auto getError = &ImGui::Backend::Glfw::GetError;
1920

2021
EXPECT_EQ(window, nullptr);
2122
EXPECT_EQ(monitor, nullptr);
@@ -26,6 +27,7 @@ TEST(ImGuiGlfwBackendModuleTest, ExposesPlatformApi) {
2627
EXPECT_NE(restoreCallbacks, nullptr);
2728
EXPECT_NE(getContentScaleForWindow, nullptr);
2829
EXPECT_NE(getContentScaleForMonitor, nullptr);
30+
EXPECT_NE(getError, nullptr);
2931
}
3032

3133
TEST(ImGuiOpenGL3BackendModuleTest, ExposesRendererApi) {
@@ -52,6 +54,7 @@ TEST(ImGuiGlfwOpenGL3BackendModuleTest, ExposesCombinedApi) {
5254
auto shutdown = &ImGui::Backend::GlfwOpenGL3::Shutdown;
5355
auto newFrame = &ImGui::Backend::GlfwOpenGL3::NewFrame;
5456
auto renderDrawData = &ImGui::Backend::GlfwOpenGL3::RenderDrawData;
57+
auto getError = &ImGui::Backend::GlfwOpenGL3::GetError;
5558

5659
EXPECT_NE(initGlfw, nullptr);
5760
EXPECT_NE(terminateGlfw, nullptr);
@@ -64,4 +67,5 @@ TEST(ImGuiGlfwOpenGL3BackendModuleTest, ExposesCombinedApi) {
6467
EXPECT_NE(shutdown, nullptr);
6568
EXPECT_NE(newFrame, nullptr);
6669
EXPECT_NE(renderDrawData, nullptr);
70+
EXPECT_NE(getError, nullptr);
6771
}

0 commit comments

Comments
 (0)