pcbjam/tests/GL_README.md
Viktor Vaczi 528ed97692 feat(test): Update wizard test to use dynamic button labels
- Test now correctly finds "Finish" button on last wizard page
- Added CLAUDE.md note about running e2e tests via npm scripts
- Simplified test to click through wizard with proper button detection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 15:17:03 +01:00

3.4 KiB

Wha# Emscripten LEGACY_GL_EMULATION - Immediate Mode Notes

Overview

This document describes the behavior and limitations of Emscripten's LEGACY_GL_EMULATION when using OpenGL immediate mode (glBegin/glEnd) in WebAssembly builds.

Key Finding: Color Per Vertex Requirement

Emscripten's immediate mode requires color to be specified per-vertex, not using OpenGL's "current color" semantic.

Standard OpenGL Behavior

In desktop OpenGL, you can set a color once and it applies to all subsequent vertices:

glBegin(GL_TRIANGLES);
    glColor3f(1.0f, 0.0f, 0.0f);  // Set current color to red
    glVertex3f(0, 0, 0);           // Uses red
    glVertex3f(1, 0, 0);           // Still uses red
    glVertex3f(0, 1, 0);           // Still uses red
glEnd();

Emscripten Behavior

In Emscripten's LEGACY_GL_EMULATION, you must call glColor*() before each glVertex*():

glBegin(GL_TRIANGLES);
    glColor3f(1.0f, 0.0f, 0.0f);  // Color for vertex 1
    glVertex3f(0, 0, 0);
    glColor3f(1.0f, 0.0f, 0.0f);  // Color for vertex 2 - REQUIRED!
    glVertex3f(1, 0, 0);
    glColor3f(1.0f, 0.0f, 0.0f);  // Color for vertex 3 - REQUIRED!
    glVertex3f(0, 1, 0);
glEnd();

Why This Happens

Emscripten's GLImmediate module calculates vertex stride based on enabled attributes:

  • Position (glVertex3f): 16 bytes (4 floats: x, y, z, w)
  • Color (glColor3f/4f): 4 bytes (4 unsigned bytes: r, g, b, a)
  • Total stride: 20 bytes per vertex

The numVertices calculation is:

numVertices = 4 * vertexCounter / stride

If color is only specified once but vertices are specified multiple times, vertexCounter won't be evenly divisible by stride, causing the assertion:

Assertion failed: `numVertices` must be an integer.

Verified Working Functions

The following immediate mode primitives work correctly with the color-per-vertex pattern:

Primitive Status Notes
GL_TRIANGLES Working RGB color interpolation works
GL_QUADS Working Use glVertex3f (glVertex2f also works)
GL_LINES Working
GL_LINE_STRIP Working
GL_LINE_LOOP Working

Unsupported Functions

  • glVertex2d - Not implemented in Emscripten, use glVertex2f or glVertex3f instead

Build Flags

Enable legacy GL emulation with these Emscripten flags:

-sLEGACY_GL_EMULATION
-sMAX_WEBGL_VERSION=2

You may see these warnings (they are expected):

WARNING: using emscripten GL emulation. This is a collection of limited workarounds, do not expect it to work.
WARNING: using emscripten GL immediate mode emulation. This is very limited in what it supports

Implications for KiCad

KiCad uses immediate mode in several places:

  1. Cursor rendering in opengl_gal.cpp
  2. Bitmap quad rendering
  3. Antialiasing overlays

Any code that sets a color once and draws multiple vertices will need modification for WASM builds.

Possible Solutions

  1. Compatibility layer: Wrap glColor/glVertex calls to automatically replicate colors
  2. Code modification: Update KiCad's GAL to always specify color per-vertex
  3. VBO migration: Convert immediate mode code to use Vertex Buffer Objects

Test Results

All immediate mode tests pass with the color-per-vertex pattern:

  • RGB triangle with smooth color interpolation
  • Yellow quad
  • White line
  • Cyan line strip
  • Magenta line loop

See apps/minimal_test.cpp for working examples.