subagent transcript
session 17f09f89
delegated task
In the FreeCAD WebAssembly build, remove STALE `#ifdef __EMSCRIPTEN__ dova = FALSE;` workarounds in Coin3D shape nodes that force slow immediate-mode
▸ Magik
In the FreeCAD WebAssembly build, remove STALE `#ifdef __EMSCRIPTEN__ dova = FALSE;` workarounds in Coin3D shape nodes that force slow immediate-mode GL rendering. These were added to work around a "solid renders once then vanishes" bug whose TRUE root cause was later found and fixed elsewhere (the glGetDoublev GL_DEPTH_CLEAR_VALUE stub, commit e2acb80aa5). Re-enabling vertex arrays lets Coin issue one glDrawElements per shape instead of per-vertex ffVertex JS marshaling — a major perf win.
FILES (all under /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/):
- shapenodes/SoIndexedFaceSet.cpp (~line 551 and ~559)
- shapenodes/SoFaceSet.cpp
- shapenodes/SoIndexedLineSet.cpp
- shapenodes/SoPointSet.cpp
- shapenodes/SoIndexedPointSet.cpp
- vrml97/IndexedFaceSet.cpp
- vrml97/IndexedLineSet.cpp
- vrml97/PointSet.cpp
TASK: In each file, find the `#ifdef __EMSCRIPTEN__` (or `#if defined(__EMSCRIPTEN__)`) block that sets `dova = FALSE;` (dova = "do vertex arrays"; the variable may also be named `dova`/`didrenderasvbo`/similar — grep each file for `__EMSCRIPTEN__` and for `= FALSE` near a vertex-array decision). REMOVE the emscripten-forced-off override so `dova` keeps its normally-computed value (which honors COIN_VERTEX_ARRAYS / SoGLVBOElement). Keep the surrounding logic intact; only delete the wasm-specific force-off. If a file's __EMSCRIPTEN__ block does something OTHER than force vertex-arrays off, leave that part — only remove the vertex-array disabling.
For each file, show the exact before/after of what you removed. Do NOT edit any other files. Do NOT build (the main agent will rebuild). Do NOT commit.
After editing, VERIFY each file still has balanced #if/#endif: `for f in <the 8 files>; do echo "== $f =="; grep -nE '__EMSCRIPTEN__|dova|#if|#endif' "$f" | head; done` and report. Report a concise list: file -> what was removed. Flag any file where you could NOT find a clear dova-force-off (so the main agent knows it may not exist there).
Fable
thinking
I need to search through these 8 files to locate the `__EMSCRIPTEN__` preprocessor blocks that are setting `dova = FALSE;`.
Fable
I'll investigate all 8 files to find the `__EMSCRIPTEN__` blocks that force vertex arrays off. Let me start by grepping each file.
Fable
⚙ Bash {"command": "cd /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/ && for f in shapenodes/SoIndexedFaceSet.cpp shapenodes/SoFaceSet.cpp shapenodes/SoIndexedLineSet.cpp shapenodes/SoPointSet.cpp shapenodes/SoIndexedPointSet.…
Fable
thinking
Looking at the grep results, I can see that `SoIndexedFaceSet.cpp` has an explicit `__EMSCRIPTEN__` block at line 546 that sets `dova = FALSE;` at line 551, but the other files don't show any `__EMSCRIPTEN__` directives in the search results. Let me double-check the grep output to make sure I'm reading this correctly.
Fable
The grep shows `__EMSCRIPTEN__` only appears in `SoIndexedFaceSet.cpp`. The other files have `dova = FALSE;` only as part of the normal (non-emscripten) logic. Let me verify this and read the relevant blocks.
Fable
⚙ Bash {"command": "cd /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/ && for f in shapenodes/SoIndexedFaceSet.cpp shapenodes/SoFaceSet.cpp shapenodes/SoIndexedLineSet.cpp shapenodes/SoPointSet.cpp shapenodes/SoIndexedPointSet.…
Fable
thinking
Only `SoIndexedFaceSet.cpp` contains an `__EMSCRIPTEN__` block among the eight files, so I need to focus on that one file. Let me examine the specific section around lines 530-590 to understand exactly what needs to be removed.
Fable
Only `SoIndexedFaceSet.cpp` contains an `__EMSCRIPTEN__` block. The other 7 files have no emscripten markers at all. Let me read the relevant block in `SoIndexedFaceSet.cpp`.
Fable
⚙ Read {"file_path": "/home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/shapenodes/SoIndexedFaceSet.cpp", "offset": 530, "limit": 55}
Fable
thinking
I found the specific code block that handles WebGL2 in Emscripten environments—it disables vertex array optimization for immediate-mode rendering since the fixed-function emulator only supports glBegin/glEnd calls, not Coin's vertex array path, which would otherwise cause geometry to disappear after the first frame.
Now I'm carefully removing this block while preserving the formatting. I need to delete lines 546-552 (the entire ifdef block) and consolidate the surrounding blank lines so there's just one blank line between the dova assignment and the vboelem declaration that follows.
Fable
Found the exact stale workaround at lines 546-552 in `SoIndexedFaceSet.cpp`. Now let me remove it.
Fable
⚙ Edit {"replace_all": false, "file_path": "/home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/shapenodes/SoIndexedFaceSet.cpp", "old_string": " SoGLDriverDatabase::isSupported(sogl_glue_instance(state), SO_GL_VERTEX_ARRAY);\n\n…
Fable
thinking
Looking at the specific lines mentioned in the task, line 559's `dova = FALSE;` is actually standard Coin logic within the conditional block, not an emscripten workaround that needs to be removed. The task reference might be pointing to where this assignment appears, but it's clearly part of the normal control flow, so I'll leave it as is.
Now I should verify the preprocessor directives are balanced throughout the file and confirm the other seven files don't contain any emscripten force-offs either. From the grep results, all the `dova = FALSE;` assignments in those files appear within `if (dova && ...)` conditional blocks, which is standard Coin logic rather than forced disabling. Let me r …
Fable
The `dova = FALSE;` at the old line 559 (now ~551) is normal Coin logic inside `if (dova && (mbind != OVERALL))`, not an emscripten force-off, so I correctly left it. Now let me verify balanced `#if`/`#endif` across all 8 files.
Fable
⚙ Bash {"command": "cd /home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/ && for f in shapenodes/SoIndexedFaceSet.cpp shapenodes/SoFaceSet.cpp shapenodes/SoIndexedLineSet.cpp shapenodes/SoPointSet.cpp shapenodes/SoIndexedPointSet.…
Fable
thinking
All the preprocessor directives are properly balanced across the files, and the EMSCRIPTEN references have been successfully removed—the exit code was just from grep returning zero matches, which is expected.
Now I'm verifying that the `dova = FALSE` assignments in the other seven files are legitimate conditional logic rather than hidden force-offs. Looking at the grep results, every instance appears within standard `if (dova && ...)` blocks that handle color VBO checks, which is normal Coin behavior. There's no unconditional `dova = FALSE` sitting outside a conditional, and no `__EMSCRIPTEN__` guards anywhere else either. The broader search for EMSCRIPTEN, `__wasm`, and WASM variants alrea …
Fable
All 8 files have balanced `#if`/`#endif`, and `EMSCRIPTEN` references are now 0 across the board. (The exit code 1 is just the trailing `grep -c` returning 0 matches plus the harmless zsh `HISTDB_FD` notice — not an error.)
## Report
The stale `dova = FALSE;` emscripten force-off existed in only **one** of the eight listed files, not all eight.
### Edited (1 file)
**`/home/magik6k/lcad-wasm/freecad-port/FreeCAD/src/3rdParty/coin/src/shapenodes/SoIndexedFaceSet.cpp`**
Removed this block (was at lines 546-552, right after the normal `dova` computation ending in `SO_GL_VERTEX_ARRAY);`):
```cpp
#ifdef __EMSCRIPTEN__
// The WebGL2 fixed-function emulator (Gui/WasmGLFixedFunc.cpp) only services
// immediate-mode glBegin/glEnd, not Coin's vertex-array/VBO draw path. Coin
// switches a static shape to vertex arrays once its normal cache is valid, so
// without this the geometry renders on the first frame and then disappears.
dova = FALSE;
#endif
```
After: the `dova` value flows straight from its normal computation into `const SoGLVBOElement * vboelem = ...` untouched. The blank-line spacing is clean and `#if`/`#endif` count is balanced (12/12).
Note: this file also has a `dova = FALSE;` at the (now shifted) line ~551 inside `if (dova && (mbind != OVERALL)) {` — that is standard upstream Coin logic (it re-enables `dova` a few lines later based on color-VBO / packed-color checks), NOT an emscripten workaround, so I left it intact. This matches the task's "~line 559" hint but that line is not a force-off.
### No change needed (7 files) — flagged: no dova-force-off present
None of the following contain any `__EMSCRIPTEN__`/`WASM` marker at all (confirmed via `grep -niE 'EMSCRIPTEN|__wasm|WASM'`), so there was nothing to remove. Every `dova = FALSE;` in them sits inside the normal `if (dova && (mbind ...))` upstream Coin decision logic, not a wasm force-off:
- `shapenodes/SoFaceSet.cpp`
- `shapenodes/SoIndexedLineSet.cpp`
- `shapenodes/SoPointSet.cpp`
- `shapenodes/SoIndexedPointSet.cpp`
- `vrml97/IndexedFaceSet.cpp`
- `vrml97/IndexedLineSet.cpp`
- `vrml97/PointSet.cpp`
So the wasm force-off was centralized in `SoIndexedFaceSet.cpp` only. If the "solid renders once then vanishes" symptom was truly fixed by the `glGetDoublev` stub (commit e2acb80aa5), this single removal should be sufficient; there were no parallel overrides to clean up in the other shape nodes. No build and no commit performed, as instructed.