subagent transcript
session 18e25685 · workflow wf_23df5b1c
delegated task
You are an adversarial verifier for a FreeCAD-wasm code review. A reviewer claims: SEVERITY: medium CATEGORY: feature-gap FILE: src/Gui/WasmGLFixedFun
▸ Magik
You are an adversarial verifier for a FreeCAD-wasm code review. A reviewer claims:
SEVERITY: medium
CATEGORY: feature-gap
FILE: src/Gui/WasmGLFixedFunc.cpp
SUMMARY: SoText2 and all raster/bitmap text render nothing because glRasterPos*, glBitmap and glDrawPixels are no-ops, and the JS-side matrices are not read-backable.
DETAIL/EVIDENCE: glRasterPos2f/3f/3fv, glBitmap, glDrawPixels are empty stubs (lines 477-481). SoText2 (dimension text, labels, coordinate/axis text, measurement annotations) draws via raster position + bitmap glyphs, so no on-screen text appears. Additionally glGetFloatv/glGetDoublev(GL_MODELVIEW_MATRIX/PROJECTION_MATRIX) are not intercepted (glGetDoublev stub returns 0 at line 465; glGetFloatv is not defined so emscripten returns nothing for these enums), so even a texture-based SoText2 that needs to project to screen cannot read back the matrices the emulator keeps in JS. FIX: implement a textured-glyph path and expose glGetFloatv(GL_MODELVIEW_MATRIX/GL_PROJECTION_MATRIX) from the JS stacks, or document text as unsupported.
RECOMMENDATION: (none)
Independently verify by reading the actual file(s) and running git/grep as needed (repo at /home/magik6k/lcad-wasm/freecad-port/FreeCAD, toolchain at /opt/toolchains, deploy at /home/magik6k/lcad-wasm/freecad-port/deploy-gui). Default to REFUTED if you cannot confirm the evidence. Adjust severity to what the evidence actually supports.
Fable
thinking
I should check the actual file to confirm what's being claimed.
Fable
⚙ Read {"file_path": "/home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/Gui/WasmGLFixedFunc.cpp"}
Fable
thinking
I'm checking the claim about those graphics functions being empty stubs—that's confirmed. Now I need to verify how SoText2 actually renders in Coin, since it traditionally uses glBitmap for text rendering, which would explain why no text appears on screen if those functions are stubbed out.
I should also confirm that glGetFloatv isn't defined anywhere in this WebAssembly port, and verify whether SoText2 in this codebase actually depends on glBitmap for rendering. Let me search the repository to check the Coin source and see how text rendering is implemented.
Fable
⚙ Bash {"command": "grep -rn \"glGetFloatv\" src/Gui/WasmGLFixedFunc.cpp; echo \"---grep whole tree for glGetFloatv defs in wasm---\"; grep -rln \"glGetFloatv\" src/Gui/ | head"}
Fable
⚙ Bash {"command": "grep -rln \"SoText2\" src/ | head -30"}
Fable
thinking
I need to check how SoText2 handles text rendering in GLRender—whether it's using glBitmap or textured glyphs for the coin source that's bundled.
Fable
⚙ Bash {"command": "grep -n \"glBitmap\\|glRasterPos\\|glDrawPixels\\|glPixelStorei\\|cc_glglue_glBitmap\\|drawPixels\\|glTexImage\\|SoGlyph\\|dumpGlyph\\|getBitmap\" src/3rdParty/coin/src/nodes/SoText2.cpp | head -40"}
Fable
⚙ Bash {"command": "grep -rn \"glGetFloatv\" src/Gui/View3DInventorViewer.cpp"}
Fable
⚙ Bash {"command": "find src/3rdParty/coin -name \"SoText2.cpp\" -o -name \"SoText2*.cpp\" 2>/dev/null; echo \"---\"; find src/3rdParty/coin/src -iname \"*text2*\"; echo \"---all text---\"; find src/3rdParty/coin/src -iname \"*text*\" | head"}
Fable
⚙ Bash {"command": "grep -n \"glBitmap\\|glRasterPos\\|glDrawPixels\\|glPixelStorei\\|cc_glglue_glBitmap\\|glPixelZoom\\|glTexImage\\|glGetFloatv\\|GL_MODELVIEW_MATRIX\\|GL_PROJECTION_MATRIX\\|glGetIntegerv\\|GL_VIEWPORT\\|dumpGlyph\\|renderString…
Fable
thinking
I'm checking the render code in those sections to trace how the entire rendering pipeline relies on glRasterPos3f, glBitmap, and glDrawPixels.
Fable
⚙ Read {"file_path": "/home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/shapenodes/SoText2.cpp", "offset": 360, "limit": 220}
Fable
thinking
I'm tracing through SoText2's GLRender implementation to understand how it handles raster positioning—specifically looking at the setRasterPos3f function around line 983 to see how it manages the bitmap and pixel drawing operations.
Fable
⚙ Read {"file_path": "/home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/shapenodes/SoText2.cpp", "offset": 960, "limit": 30}
Fable
thinking
So SoText2 relies entirely on three OpenGL functions that are stubbed out as no-ops in the WebAssembly implementation, meaning it wouldn't render anything. Now I need to verify whether FreeCAD actually uses SoText2 for the purposes mentioned—dimension text, labels, coordinate and axis text, measurement annotations—by searching the codebase.
Fable
⚙ Bash {"command": "grep -rln \"SoText2\" src/Gui src/Mod 2>/dev/null | grep -v 3rdParty | head -30"}
Fable
thinking
SoText2 is widely used throughout the codebase—in color legends, axis crosses, bounding boxes, draft dimensions, measurement views, and annotations. But there's a critical limitation: the OpenGL matrix queries for modelview and projection matrices aren't being intercepted, which means even if SoText2 were texture-based and needed to project coordinates to screen space, it couldn't access those matrices to do so.
Actually, looking at the GLRender code more carefully, it's pulling the projection matrix from SoProjectionMatrixElement in Coin's state rather than calling glGetFloatv directly. Let me trace where that matrix originates in the GLRender initialization.
Fable
⚙ Read {"file_path": "/home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/shapenodes/SoText2.cpp", "offset": 330, "limit": 30}
Fable
thinking
The reviewer's claim about texture-based SoText2 needing to read back matrices is actually speculative—the real implementation uses Coin's matrix elements directly rather than glGetFloatv, so that part of the argument loses some force. The reviewer framed it as a hypothetical scenario, but the actual evidence doesn't quite support it.
The core claim holds up though: glGetFloatv doesn't intercept MODELVIEW/PROJECTION matrices, and glGetDoublev returns 0. But that's not what actually breaks SoText2—it's the raster and bitmap operations being no-ops that cause the rendering failure. So the main conclusion (SoText2 renders nothing) is confirmed, even if the matrix-readback reasoning is secondar …
Fable
⚙ Bash {"command": "grep -rln \"glBitmap\\|glRasterPos3f\\|glDrawPixels\" src/Gui src/App 2>/dev/null | grep -v 3rdParty; echo \"=== any other def of these symbols in wasm-specific files ===\"; grep -rn \"void glBitmap\\|void glRasterPos3f\\|void …
Fable
thinking
I've confirmed these symbols are no-ops in the wasm port and Text2 rendering depends entirely on them. Now I'm checking the glGetDoublev stub at line 465 and whether glGetFloatv handles MODELVIEW/PROJECTION matrices—I see it's called in View3DInventorViewer.cpp with GL_COLOR_CLEAR_VALUE, which should be straightforward.
Actually, glGetFloatv isn't defined in WasmGLFixedFunc.cpp at all—emscripten's real implementation handles it. But since emscripten doesn't know about the JS-side matrix stacks, querying GL_MODELVIEW_MATRIX or GL_PROJECTION_MATRIX would fail because those are legacy enums removed from WebGL2. This confirms the reviewer's point about matrix readback not being possible.
The m …
Fable
I've verified all the key claims by reading the actual files.
**Primary claim — CONFIRMED.** In `src/Gui/WasmGLFixedFunc.cpp`, `glRasterPos2f`/`glRasterPos3f`/`glRasterPos3fv` (lines 477-479), `glBitmap` (480), and `glDrawPixels` (481) are all empty no-op stubs, and these are the only definitions of those symbols in the FreeCAD-side tree (nothing else overrides them).
Coin's `SoText2::GLRender` (`src/3rdParty/coin/src/shapenodes/SoText2.cpp`) depends entirely on this path: mono glyphs go through `SoText2P::setRasterPos3f` (line 973) → `glRasterPos3f` + `glBitmap` (983-984, 468), and anti-aliased glyphs are composited into a pixel buffer flushed via `glDrawPixels` (line 545). With all three being no-ops, SoText2 emits nothing to the framebuffer.
`SoText2` is used broadly across FreeCAD Gui/Mod (color legend/`SoFCColorLegend`, `SoAxisCrossKit`, `SoFCBoundingBox` dims, Draft dimensions/labels/text, Measure view providers, annotations), so the "no on-screen text" impact is real and wide.
**Secondary claim (matrix readback) — factually true but a weaker/partly-speculative point.** `glGetDoublev` returns 0 (line 465), and `glGetFloatv` is not defined here (emscripten's real one handles the `GL_COLOR_CLEAR_VALUE` call at View3DInventorViewer.cpp:3322, and would not know about the JS `__ff` matrix stacks). So `GL_MODELVIEW_MATRIX`/`GL_PROJECTION_MATRIX` indeed cannot be read back. However, this is *not* what breaks current SoText2: its GLRender reads matrices from Coin's own state elements (`SoModelMatrixElement`/`SoViewingMatrixElement`/`SoProjectionMatrixElement`, lines 357-359), not from `glGetFloatv`. The reviewer frames it as a blocker for a hypothetical "texture-based SoText2," which is accurate as stated but doesn't add to the actual current-code defect.
**Severity — medium is appropriate.** The core defect (all raster/bitmap text invisible) is solidly evidenced and affects many features, but this is an explicitly limited fixed-function emulation shim (file header scopes it to "the FreeCAD viewport subset," with text among the listed remaining no-ops), so it's a known feature gap rather than a regression, consistent with the reviewer's own "document as unsupported" alternative.
Fable
⚙ StructuredOutput {"verdict": "CONFIRMED", "reason": "Verified in WasmGLFixedFunc.cpp: glRasterPos2f/3f/3fv (477-479), glBitmap (480), glDrawPixels (481) are all empty no-op stubs and the only definitions of those symbols. Coin's SoText2::GLRender (src/3rdPa…