Add feature branch patch management system

Rename docs/ to features/ with per-feature folders. Add script to generate
patches for root repo and submodules.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Viktor Vaczi 2026-01-06 16:17:52 +01:00
commit 5147917ea7
5 changed files with 187 additions and 0 deletions

152
features/ipc-api/ipc-api.md Normal file
View file

@ -0,0 +1,152 @@
# KiCad IPC API - WASM Fork Changes
## Overview
We added `#ifdef KICAD_IPC_API` guards to 18 KiCad source files. These guards wrap:
- `#include` statements for protobuf/API headers
- `Serialize()` and `Deserialize()` methods
**Key insight:** Since our build uses `KICAD_IPC_API=ON` (line 251 of `scripts/kicad/build-pcbnew.sh`), these guards don't actually disable any code - everything compiles. The guards can be safely reverted to reduce fork divergence.
## Modified Files
| File | What We Guarded |
|------|-----------------|
| `common/eda_shape.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `common/eda_text.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `common/netclass.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `include/api/api_utils.h` | Entire namespace content (utility functions) |
| `pcbnew/api/api_pcb_utils.h` | Entire file content |
| `pcbnew/board_connected_item.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/board_stackup_manager/board_stackup.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/footprint.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/pad.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/padstack.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/pcb_dimension.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/pcb_field.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/pcb_group.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/pcb_shape.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/pcb_text.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/pcb_textbox.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/pcb_track.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
| `pcbnew/zone.cpp` | `#include` for API headers, `Serialize()`, `Deserialize()` |
## Example of Our Changes
**Before (upstream):**
```cpp
#include <api/api_enums.h>
#include <api/api_utils.h>
#include <api/board/board_types.pb.h>
void PAD::Serialize( google::protobuf::Any &aContainer ) const
{
// ... serialization code
}
```
**After (our fork):**
```cpp
#ifdef KICAD_IPC_API
#include <api/api_enums.h>
#include <api/api_utils.h>
#include <api/board/board_types.pb.h>
#endif
#ifdef KICAD_IPC_API
void PAD::Serialize( google::protobuf::Any &aContainer ) const
{
// ... serialization code
}
#endif
```
## Why We Added These Guards
Originally added to allow building with `KICAD_IPC_API=OFF`, which would:
- Skip protobuf dependency
- Exclude serialization methods that depend on protobuf types
However, our current build has `KICAD_IPC_API=ON`, making these guards unnecessary.
## How to Revert
To revert these files to upstream (base commit `4bfed3f174`):
```bash
cd kicad
git checkout 4bfed3f174 -- \
common/eda_shape.cpp \
common/eda_text.cpp \
common/netclass.cpp \
include/api/api_utils.h \
pcbnew/api/api_pcb_utils.h \
pcbnew/board_connected_item.cpp \
pcbnew/board_stackup_manager/board_stackup.cpp \
pcbnew/footprint.cpp \
pcbnew/pad.cpp \
pcbnew/padstack.cpp \
pcbnew/pcb_dimension.cpp \
pcbnew/pcb_field.cpp \
pcbnew/pcb_group.cpp \
pcbnew/pcb_shape.cpp \
pcbnew/pcb_text.cpp \
pcbnew/pcb_textbox.cpp \
pcbnew/pcb_track.cpp \
pcbnew/zone.cpp
```
Then rebuild:
```bash
./docker/build.sh --clean-kicad
```
## Note: toolbars_pcb_editor.cpp
This file has `#ifdef KICAD_SCRIPTING` guards (not IPC API guards):
```cpp
#ifdef KICAD_SCRIPTING
#include "../scripting/python_scripting.h"
#endif
...
#ifdef KICAD_SCRIPTING
bool scriptingAvailable = SCRIPTING::IsWxAvailable();
#else
bool scriptingAvailable = false;
#endif
```
**Cannot be fully reverted** because:
- `KICAD_SCRIPTING=OFF` for WASM builds (CMakeLists.txt lines 135-138)
- Without guards, build fails (python_scripting.h not built, SCRIPTING class doesn't exist)
This is a separate concern from the IPC API and is documented here for completeness.
## Impact of Reversion
- **Fork diff reduction:** 18 fewer modified files
- **Build behavior:** No change (KICAD_IPC_API=ON, code compiles identically)
- **Functionality:** No change (serialization methods still available)
## Related: IPC API Architecture
KiCad's IPC API uses:
- **Protobuf messages** for request/response serialization
- **NNG sockets** for transport (stubbed in WASM - see `wasm/stubs/nng_stub.c`)
- **API_HANDLER_PCB** class for handling requests (instantiated in PCB_EDIT_FRAME)
Our stub at `wasm/stubs/api_plugin_stub.cpp` provides no-op implementations for:
- `KICAD_API_SERVER::Start()`, `Stop()`, `Running()`
- `KICAD_API_SERVER::RegisterHandler()`, `DeregisterHandler()`
## Future: JavaScript Bridge
To expose the IPC API to JavaScript (optional enhancement):
1. Modify `api_plugin_stub.cpp` to store registered handlers
2. Create Embind bindings in `wasm/bindings/api_bridge.cpp`
3. Expose `KiCadApi_HandleRequest(protobufData)` function
4. Use `protobuf.js` on JS side for message creation/parsing
This would enable JS automation without modifying any KiCad source files.

View file

@ -0,0 +1,262 @@
# OpenGL, GAL, and WebGL Strategy for KiCad WASM
## Summary
This document analyzes KiCad's graphics architecture and evaluates strategies for WebGL rendering in the WASM build.
## Current Implementation: Emscripten LEGACY_GL_EMULATION
We currently use Emscripten's legacy OpenGL emulation:
```bash
-sLEGACY_GL_EMULATION -sMAX_WEBGL_VERSION=2
```
**How it works:**
```
KiCad/wxWidgets C++ (glBegin, glVertex, glColor, etc.)
│
▼
gl_immediate_shim.js (our fix for color-per-vertex bug)
│
▼
Emscripten GLImmediate (translates legacy GL → shaders + VBOs)
│
▼
WebGL 2.0 (ES 3.0 compatible, shader-based)
```
**Key components:**
| Component | File | Purpose |
|-----------|------|---------|
| wxGLCanvas | `wxwidgets/src/wasm/glcanvas.cpp` | Creates WebGL contexts on dedicated HTML5 canvases |
| GL Shim | `wasm/shims/gl_immediate_shim.js` | Fixes color-per-vertex bug in GLImmediate |
| GLU Tesselator | `wasm/stubs/glu_wasm_impl.cpp` | Polygon triangulation using earcut (GLU not available in WebGL) |
| GLEW Stub | `wasm/cmake/FindGLEW.cmake` | Stubs out GLEW (not needed with Emscripten) |
| kiglew.h | `kicad/include/gal/opengl/kiglew.h` | Maps double→float, stubs unsupported functions |
---
## GLU Status
**KiCad uses GLU** for polygon tesselation (`gluTess*` functions for zones, complex shapes).
**We already solved this** with `/wasm/stubs/glu_wasm_impl.cpp` which implements the GLU tesselator API using KiCad's earcut algorithm. This works with both LEGACY_GL_EMULATION and would work with pure ES3.
GLU is NOT a blocker.
---
## Where KiCad Uses Legacy OpenGL
Two separate systems use legacy OpenGL:
### 1. OPENGL_GAL (2D Rendering)
Used for schematic and PCB editors.
**Files:**
- `kicad/common/gal/opengl/opengl_gal.cpp` - Main implementation
- `kicad/common/gal/opengl/gpu_manager.cpp` - VBO management
- `kicad/common/gal/opengl/opengl_compositor.cpp` - Framebuffer compositing
- `kicad/common/gal/opengl/antialiasing.cpp` - AA effects
**Legacy GL usage in opengl_gal.cpp:**
- Lines 1557-1605: Bitmap rendering with `glBegin(GL_QUADS)`
- Lines 2690-2755: Cursor drawing with `glBegin(GL_LINES)`
- Lines 566-629, 1558-1602, 2704-2751: Matrix stack operations (`glPushMatrix`, `glPopMatrix`, `glMatrixMode`)
### 2. 3D Viewer (3D Rendering)
Separate from GAL, used for 3D board visualization.
**Files using legacy GL:**
- `kicad/3d-viewer/3d_rendering/opengl/render_3d_opengl.cpp`
- `kicad/3d-viewer/3d_rendering/opengl/opengl_utils.cpp`
- `kicad/3d-viewer/3d_rendering/opengl/layer_triangles.cpp`
- `kicad/3d-viewer/3d_rendering/opengl/3d_spheres_gizmo.cpp`
- `kicad/3d-viewer/3d_rendering/opengl/3d_model.cpp`
- `kicad/3d-viewer/3d_model_viewer/eda_3d_model_viewer.cpp`
- `kicad/3d-viewer/3d_canvas/eda_3d_canvas_pivot.cpp`
---
## If We Cover GAL, Is That Enough?
**For 2D editing (schematic + PCB): YES**
The entire 2D rendering pipeline goes through GAL. A working GAL backend enables full schematic and PCB editing.
**For 3D viewer: NO**
The 3D viewer is a separate rendering system. It could be disabled/stubbed initially and added later.
---
## The GAL API
GAL (Graphics Abstraction Layer) is a clean 2D drawing interface defined in `kicad/include/gal/graphics_abstraction_layer.h`.
**NO raw OpenGL is exposed.** The API consists of ~40 virtual methods:
```cpp
// Drawing primitives
virtual void DrawLine(const VECTOR2D& start, const VECTOR2D& end);
virtual void DrawSegment(const VECTOR2D& start, const VECTOR2D& end, double width);
virtual void DrawPolyline(const std::vector<VECTOR2D>& points);
virtual void DrawCircle(const VECTOR2D& center, double radius);
virtual void DrawArc(const VECTOR2D& center, double radius, const EDA_ANGLE& start, const EDA_ANGLE& angle);
virtual void DrawRectangle(const VECTOR2D& start, const VECTOR2D& end);
virtual void DrawPolygon(const SHAPE_POLY_SET& polySet);
virtual void DrawBitmap(const BITMAP_BASE& bitmap, double alpha);
virtual void DrawGlyph(const KIFONT::GLYPH& glyph);
// Attributes
virtual void SetFillColor(const COLOR4D& color);
virtual void SetStrokeColor(const COLOR4D& color);
virtual void SetLineWidth(float width);
virtual void SetIsFill(bool enabled);
virtual void SetIsStroke(bool enabled);
virtual void SetLayerDepth(double depth);
// Transforms (matrix stack)
virtual void Save();
virtual void Restore();
virtual void Transform(const MATRIX3x3D& matrix);
virtual void Rotate(double angle);
virtual void Translate(const VECTOR2D& translation);
virtual void Scale(const VECTOR2D& scale);
// Rendering control
virtual void BeginDrawing();
virtual void EndDrawing();
virtual void SetTarget(RENDER_TARGET target);
virtual void ClearTarget(RENDER_TARGET target);
virtual void ClearScreen();
// Grid and cursor
virtual void DrawGrid();
virtual void DrawCursor(const VECTOR2D& position);
```
**Existing GAL implementations:**
| Class | File | Purpose |
|-------|------|---------|
| `OPENGL_GAL` | `kicad/include/gal/opengl/opengl_gal.h` | OpenGL rendering (uses legacy GL internally) |
| `CAIRO_GAL` | `kicad/include/gal/cairo/cairo_gal.h` | Cairo software rendering |
| `CALLBACK_GAL` | `kicad/include/callback_gal.h` | Hit testing, no actual rendering |
---
## What Breaks with FULL_ES3 (No Legacy Emulation)
If we removed `LEGACY_GL_EMULATION`:
| Feature | Used In | Status in FULL_ES3 |
|---------|---------|-------------------|
| `gluTess*` (tesselation) | Polygon rendering | **Our stub works** |
| `glBegin/glEnd` | Bitmap quads, cursor | Not available |
| `glVertex/glColor` | Immediate mode drawing | Not available |
| `glPushMatrix/glPopMatrix` | Transformations | Not available |
| `glMatrixMode` | Matrix switching | Not available |
| `GL_QUADS` | Bitmap rendering | Not available (only triangles) |
| `glEnableClientState` | Legacy vertex arrays | Not available |
---
## Strategy Options
### Option 1: Keep LEGACY_GL_EMULATION (Current)
**Pros:**
- Works now
- Minimal code changes to KiCad
- All immediate mode functions available
**Cons:**
- ~200KB binary overhead from GLImmediate
- Runtime overhead from emulation
- Color-per-vertex bug requires our shim
- Some edge cases may not work
**Build flags:**
```bash
-sLEGACY_GL_EMULATION -sMAX_WEBGL_VERSION=2
```
### Option 2: Create WEBGL_GAL (New Backend)
Create a new GAL implementation that uses pure WebGL 2.0 (ES 3.0) without legacy emulation.
**Pros:**
- No emulation overhead
- Smaller binary
- Cleaner, more maintainable
- Better performance
**Cons:**
- Development effort (~2-3 weeks)
- Need to maintain separate backend
**Estimated scope:**
```
New class: WEBGL_GAL : public GAL
Files needed:
├── webgl_gal.h (~300 lines)
├── webgl_gal.cpp (~2500 lines)
├── webgl_shaders.cpp (~500 lines)
└── webgl_compositor.cpp (~500 lines)
Total: ~3500-4000 lines
```
**Why it's feasible:**
- GAL API is clean - no raw GL leaks through
- CAIRO_GAL proves it works (~2500 lines)
- All drawing is 2D with simple primitives
- KiCad's shaders already exist and work in WebGL
### Option 3: Cairo-only (Software Rendering)
Use CAIRO_GAL exclusively, render to HTML5 2D canvas.
**Pros:**
- Already exists
- No WebGL needed
- Works everywhere
**Cons:**
- Slow (CPU-only)
- May struggle with complex boards
- No hardware acceleration
---
## Recommendation
**Short-term:** Keep LEGACY_GL_EMULATION - it works and allows rapid development.
**Medium-term:** Create WEBGL_GAL - cleaner architecture, better performance, removes emulation hacks.
**For 3D viewer:** Disable initially, add later as separate effort.
---
## Key Files Reference
| Purpose | File |
|---------|------|
| Build flags | `scripts/common/env.sh` |
| wxGLCanvas WASM | `wxwidgets/src/wasm/glcanvas.cpp` |
| GL immediate shim | `wasm/shims/gl_immediate_shim.js` |
| GLU tesselator | `wasm/stubs/glu_wasm_impl.cpp` |
| KiCad GL compat | `kicad/include/gal/opengl/kiglew.h` |
| KiCad shaders | `kicad/common/gal/shaders/kicad_*.glsl` |
| GAL base class | `kicad/include/gal/graphics_abstraction_layer.h` |
| OPENGL_GAL | `kicad/include/gal/opengl/opengl_gal.h` |
| CAIRO_GAL | `kicad/include/gal/cairo/cairo_gal.h` |
| GL documentation | `tests/GL_README.md` |