Add research doc: OpenGL, GAL, and WebGL strategy
Documents: - Current LEGACY_GL_EMULATION implementation - GLU tesselator status (solved with earcut) - Where KiCad uses legacy GL (OPENGL_GAL + 3D Viewer) - The GAL API abstraction (~40 clean methods) - Strategy options: keep emulation vs create WEBGL_GAL - Recommendation for short/medium term approach 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
251056e506
commit
ca4f7eb40d
1 changed files with 262 additions and 0 deletions
262
docs/research/0001-opengl-gal-webgl-strategy.md
Normal file
262
docs/research/0001-opengl-gal-webgl-strategy.md
Normal 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` |
|
||||
Loading…
Reference in a new issue