feat(3d): gl1 shim M4+M6+M7 — GLU quadrics, production link, stub retired; 47/47 parity
- gl1_glu: gluCylinder/gluDisk/gluSphere per the SGI GLU reference tessellation (sin/cos phase, strip emission order, pole fans — Apple's GLU derives from the same source, so vertices match the goldens); emission goes through the public glBegin/glVertex entry points so quadrics record into display lists - glLineWidth>1 one-time warning (browsers clamp to 1; affected coverage stays under the parity floor — zero floors.json overrides needed) - production link site: build-kicad-target.sh now compiles wasm/gl1 from sources.txt and applies wrapped_symbols.txt --wrap flags (same manifests as the test harness); kicad_editor's RENDER_3D_OPENGL links against the real emulation layer instead of no-ops - wasm/stubs/gl_ffp_stub.c deleted (role fully superseded; history in git) - docs: 3d-regression README port-status section (floor-blind small geometry + line-width caveats), harness comments de-red-stated Parity: 47/47 under the 0.02 floor, zero overrides. Native golden path byte-identical to bb0e238 (whose gate ran green) — scenarios/, native/, baseline/, manifest, floors, spec all untouched by the port. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
3fe4f6fb00
commit
27992f4f18
8 changed files with 240 additions and 157 deletions
|
|
@ -3,8 +3,8 @@
|
|||
# Build script for the 3D-renderer WebGL test harness (WASM).
|
||||
#
|
||||
# Builds the shared 3D scenarios (tests/3d-regression/scenarios) + real KiCad
|
||||
# 3D-viewer TUs against the FFP no-op stubs (wasm/stubs/gl_ffp_stub.c) — the
|
||||
# TDD red state for the OpenGL->WebGL port. Output: tests/apps/3d-webgl/.
|
||||
# 3D-viewer TUs against the wasm/gl1 GL1->WebGL2 emulation layer (the
|
||||
# OpenGL->WebGL port). Output: tests/apps/3d-webgl/.
|
||||
#
|
||||
# Requires the wxWidgets WASM build (scripts/build-wx-wasm.sh) and the sysroot
|
||||
# headers (boost/glm) in build-wasm/sysroot.
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
# ./scripts/build-3d-webgl-test.sh --debug # Debug build with source maps
|
||||
#
|
||||
# Modeled on scripts/build-gal-webgl-test.sh (no shader-generation step — the
|
||||
# FFP renderer has no GLSL yet; the port will add one here).
|
||||
# gl1 shim's FFP uber-shader lives inline in wasm/gl1/src/gl1_shaders.cpp).
|
||||
#
|
||||
|
||||
source "$(dirname "$0")/common/logging.sh"
|
||||
|
|
|
|||
|
|
@ -445,24 +445,36 @@ if [ "${APP_NAME}" = "occ_service" ]; then
|
|||
fi
|
||||
|
||||
# 3D viewer: built by DEFAULT (BUILD_3D_VIEWER=ON). Opt out with BUILD_3D_VIEWER=OFF, which links the
|
||||
# 3D stubs instead. The 3D viewer renders with the GL-free CPU raytracer (RENDER_3D_RAYTRACE_RAM)
|
||||
# blitted to the canvas through a plain WebGL2 textured quad — no -sLEGACY_GL_EMULATION. KiCad's
|
||||
# fixed-function OpenGL renderer is still compiled (shared files reference it) but never executed on
|
||||
# WASM, so its FFP/GLU entry points are satisfied at link time by no-op stubs (gl_ffp_stub.c). The
|
||||
# KiCad CMake option KICAD_BUILD_3D_VIEWER_WASM stays OFF upstream; our build passes it explicitly.
|
||||
# See docs/features/fork-cleanup/10-3d-viewer.md.
|
||||
# 3D stubs instead. The default renderer is still the GL-free CPU raytracer
|
||||
# (RENDER_3D_RAYTRACE_RAM) blitted through a WebGL2 textured quad, but KiCad's fixed-function
|
||||
# OpenGL renderer (RENDER_3D_OPENGL) now links against the REAL GL1->WebGL2 emulation layer
|
||||
# (wasm/gl1, no -sLEGACY_GL_EMULATION): the shim implements the FFP-only entry points and
|
||||
# --wrap-intercepts the Emscripten-owned names it must observe (wasm/gl1/wrapped_symbols.txt).
|
||||
# Regression gate: tests/3d-regression (47 golden scenarios). The KiCad CMake option
|
||||
# KICAD_BUILD_3D_VIEWER_WASM stays OFF upstream; our build passes it explicitly.
|
||||
# See wasm/gl1/README.md and docs/features/fork-cleanup/10-3d-viewer.md.
|
||||
BUILD_3D_VIEWER="${BUILD_3D_VIEWER:-ON}"
|
||||
GL3D_LINK_FLAGS=""
|
||||
if [ "${BUILD_3D_VIEWER}" = "ON" ]; then
|
||||
log_info "3D viewer ENABLED for WASM (BUILD_3D_VIEWER=ON)"
|
||||
emcc -c -I"${STUBS_DIR}" "${STUBS_DIR}/gl_ffp_stub.c" -o "${STUBS_BUILD}/gl_ffp_stub.o"
|
||||
GL3D_LINK_FLAGS="${STUBS_BUILD}/gl_ffp_stub.o"
|
||||
log_info "3D viewer ENABLED for WASM (BUILD_3D_VIEWER=ON) — compiling wasm/gl1 FFP shim"
|
||||
GL1_DIR="${PROJECT_ROOT}/wasm/gl1"
|
||||
while IFS= read -r gl1_src; do
|
||||
[ -n "${gl1_src}" ] || continue
|
||||
em++ -c ${EXTRA_FLAGS} -pthread -std=c++20 \
|
||||
-I"${GL1_DIR}/include" -I"${STUBS_DIR}" -I"${SYSROOT}/include" \
|
||||
"${GL1_DIR}/src/${gl1_src}" -o "${STUBS_BUILD}/${gl1_src%.cpp}.o"
|
||||
GL3D_LINK_FLAGS="${GL3D_LINK_FLAGS} ${STUBS_BUILD}/${gl1_src%.cpp}.o"
|
||||
done < "${GL1_DIR}/sources.txt"
|
||||
while IFS= read -r gl1_sym; do
|
||||
[ -n "${gl1_sym}" ] || continue
|
||||
GL3D_LINK_FLAGS="${GL3D_LINK_FLAGS} -Wl,--wrap=${gl1_sym}"
|
||||
done < "${GL1_DIR}/wrapped_symbols.txt"
|
||||
fi
|
||||
|
||||
# Multi-threaded CPU raytracer (mainline threading restored): link the main-thread
|
||||
# nanosleep->Asyncify-yield shim so the raw-thread raytracer joins (sleep_for busy-wait)
|
||||
# yield to the JS event loop instead of deadlocking on-demand pthread-Worker creation.
|
||||
# Mirrors the gl_ffp_stub pattern (compile to .o, add to the link). Shim:
|
||||
# Mirrors the wasm/gl1 pattern (compile to .o, add to the link). Shim:
|
||||
# wasm/shims/nanosleep_yield.c; its EM_ASYNC_JS yield is covered by env.__asyncjs__* in
|
||||
# scripts/common/asyncify-imports.txt.
|
||||
emcc -c -pthread "${PROJECT_ROOT}/wasm/shims/nanosleep_yield.c" -o "${STUBS_BUILD}/nanosleep_yield.o"
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@ compiled two ways:
|
|||
the vendored glad loader). Renders each scenario into a fixed 800×600
|
||||
offscreen FBO (`GL_RGBA8` + `GL_DEPTH24_STENCIL8`, the
|
||||
`EDA_3D_CANVAS::RenderToFrameBuffer` recipe) → **golden baselines**.
|
||||
- **wasm/** — the same scenario TUs compiled with em++ (planned; red state
|
||||
first: linked against `wasm/stubs/gl_ffp_stub.c` no-ops, every render blank
|
||||
until the port makes them green).
|
||||
- **wasm/** — the same scenario TUs compiled with em++, linked against the
|
||||
**`wasm/gl1`** GL1→WebGL2 emulation layer (the port itself — see
|
||||
`wasm/gl1/README.md`). Since the port landed, all 47 scenarios render under
|
||||
the parity floor with zero per-scenario overrides.
|
||||
|
||||
## Directory layout
|
||||
|
||||
|
|
@ -74,13 +75,22 @@ every run, so a scenario registry change can't silently drift past the
|
|||
baselines. Scenario names are append-only — never rename or renumber (they are
|
||||
the PNG names and the WebGL test IDs).
|
||||
|
||||
## TDD red state
|
||||
## Port status (was: TDD red state)
|
||||
|
||||
Once `wasm/` exists, the Playwright spec (`tests/e2e/3d-webgl.spec.ts`) is
|
||||
capture-only and stays green; the red signal is `npm run 3d:check:parity`
|
||||
reporting ~100% changed for every scenario. Port progress = scenarios dropping
|
||||
out of that report. `glLineWidth > 1` (model bbox scenario) has no WebGL
|
||||
equivalent — expect that one to need quad emulation to go green.
|
||||
The suite drove the port TDD-style: the harness started against no-op FFP
|
||||
stubs (~100% changed everywhere), and the `wasm/gl1` emulation layer ground
|
||||
the parity report down milestone by milestone (substrate → lighting →
|
||||
display lists/arrays → GLU quadrics). **Current state: 47/47 under the 0.02
|
||||
parity floor, no floors.json overrides needed.**
|
||||
|
||||
Two caveats the parity floor cannot see (verified by eyeballing renders):
|
||||
|
||||
- Small-geometry scenarios (the GLU arrows, the spheres gizmo, sparse grids)
|
||||
fit under the floor even when absent — a regression there needs the
|
||||
triptych/eyeball check, not just the report.
|
||||
- `glLineWidth > 1` is clamped to 1 by browsers (gizmo axes, native width
|
||||
2–4 lines render thinner); the affected coverage is small enough to stay
|
||||
under the floor.
|
||||
|
||||
## Scenario tiers (47 scenarios)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
* 3D-renderer WebGL test harness (WASM) — runs the shared scenarios
|
||||
* (tests/3d-regression/scenarios/) in the browser. Today the legacy GL
|
||||
* surface is wasm/stubs/gl_ffp_stub.c no-ops, so every scenario renders a
|
||||
* black canvas: the TDD red state the WebGL port turns green.
|
||||
* (tests/3d-regression/scenarios/) in the browser. The legacy GL surface is
|
||||
* implemented by the wasm/gl1 GL1->WebGL2 emulation layer; the parity level
|
||||
* (npm run 3d:check:parity) compares these renders against the native goldens.
|
||||
*
|
||||
* Unlike the GAL harness this needs no wx window: the renderer draws into
|
||||
* whatever context is current, so a direct emscripten WebGL2 context on
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
# Makefile for the 3D-renderer WebGL test harness (WASM) — TDD RED STATE.
|
||||
# Makefile for the 3D-renderer WebGL test harness (WASM).
|
||||
#
|
||||
# Compiles the SAME shared scenarios + real KiCad 3D-viewer TUs as the native
|
||||
# golden generator (tests/3d-regression/native/CMakeLists.txt), but links the
|
||||
# fixed-function GL surface against wasm/stubs/gl_ffp_stub.c no-ops — exactly
|
||||
# how the production kicad build satisfies RENDER_3D_OPENGL's link today.
|
||||
# Every scenario therefore renders BLANK until the WebGL port replaces those
|
||||
# stubs; `npm run 3d:check:parity` is the port-progress meter.
|
||||
# golden generator (tests/3d-regression/native/CMakeLists.txt), linking the
|
||||
# fixed-function GL surface against the wasm/gl1 GL1->WebGL2 emulation layer —
|
||||
# exactly how the production kicad build satisfies RENDER_3D_OPENGL's link.
|
||||
# `npm run 3d:check:parity` compares the browser renders against the native
|
||||
# goldens (47/47 under floor since the port).
|
||||
#
|
||||
# Usage:
|
||||
# make # Build
|
||||
|
|
@ -96,7 +96,7 @@ TESTIMPL_SRCS = ../native/board_adapter_test_impl.cpp \
|
|||
../native/render3d_test_accessor.cpp
|
||||
|
||||
# Same real-KiCad TU list as the native CMakeLists (minus glad — Emscripten
|
||||
# provides the modern GL surface, gl_ffp_stub.c the legacy one).
|
||||
# provides the modern GL surface, wasm/gl1 the legacy one).
|
||||
KICAD_3D_SRCS = \
|
||||
$(KICAD_ROOT)/3d-viewer/common_ogl/ogl_utils.cpp \
|
||||
$(KICAD_ROOT)/3d-viewer/3d_rendering/image.cpp \
|
||||
|
|
|
|||
|
|
@ -1,19 +1,49 @@
|
|||
/*
|
||||
* gl1_glu — GLU quadrics and gluPerspective.
|
||||
*
|
||||
* M4 ports the SGI GLU reference tessellation (quad.c) for
|
||||
* gluCylinder/gluDisk/gluSphere — the native goldens were rendered with
|
||||
* Apple's SGI-derived GLU, so vertex placement and emission order must match.
|
||||
* The quadrics emit through the shim's internal immediate-mode path
|
||||
* (immBegin/immVertex/immEnd) so they also record into display lists.
|
||||
* The tessellation follows the SGI GLU reference implementation (the
|
||||
* OpenGL Sample Implementation's libutil/quad.c, SGI Free Software License
|
||||
* B) restricted to what the renderer uses: GLU_FILL draw style, GLU_SMOOTH
|
||||
* normals, GLU_OUTSIDE orientation, no texture coordinates. Apple's GLU —
|
||||
* which rendered the native goldens — derives from the same source, so
|
||||
* vertex placement (sin/cos phase), emission order and stack/slice loops
|
||||
* must match exactly for pixel parity.
|
||||
*
|
||||
* Note: the GLU *tesselator* (gluNewTess & co, declared in the same
|
||||
* Geometry is emitted through the shim's public immediate-mode entry points
|
||||
* (glBegin/glNormal3f/glVertex3f/glEnd), so quadrics drawn between
|
||||
* glNewList/glEndList record into the display list like any other geometry.
|
||||
*
|
||||
* The GLU *tesselator* (gluNewTess & co, declared in the same
|
||||
* wasm/stubs/GL/glu.h) is a separate concern implemented in
|
||||
* kicad/libs/kimath/glu_tess/ — not part of this shim.
|
||||
*/
|
||||
|
||||
#include "gl1_shim.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const double GLU_PI = 3.14159265358979323846;
|
||||
|
||||
// SGI's normal3f helper: normalize, then emit.
|
||||
void emitNormal( float x, float y, float z )
|
||||
{
|
||||
const float mag = std::sqrt( x * x + y * y + z * z );
|
||||
|
||||
if( mag > 0.00001f )
|
||||
{
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
}
|
||||
|
||||
glNormal3f( x, y, z );
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
|
|
@ -68,33 +98,164 @@ void gluQuadricNormals( GLUquadric* q, GLenum normals )
|
|||
void gluCylinder( GLUquadric* q, double base, double top, double height, int slices, int stacks )
|
||||
{
|
||||
(void) q;
|
||||
(void) base;
|
||||
(void) top;
|
||||
(void) height;
|
||||
(void) slices;
|
||||
(void) stacks;
|
||||
GL1_WARN_ONCE( "gluCylinder not implemented yet (M4) — geometry dropped" );
|
||||
|
||||
if( slices < 2 || stacks < 1 || height == 0.0 )
|
||||
return;
|
||||
|
||||
const float da = (float) ( 2.0 * GLU_PI / slices );
|
||||
const float dr = (float) ( ( top - base ) / stacks );
|
||||
const float dz = (float) ( height / stacks );
|
||||
const float nz = (float) ( ( base - top ) / height ); // combined with (x,y), normalized
|
||||
|
||||
float t = 0.0f;
|
||||
float z = 0.0f;
|
||||
float r = (float) base;
|
||||
|
||||
for( int j = 0; j < stacks; j++ )
|
||||
{
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
|
||||
for( int i = 0; i <= slices; i++ )
|
||||
{
|
||||
// SGI closes the strip with the angle-0 vertex, not slice*da.
|
||||
const float a = ( i == slices ) ? 0.0f : (float) i * da;
|
||||
const float x = std::sin( a );
|
||||
const float y = std::cos( a );
|
||||
|
||||
emitNormal( x, y, nz );
|
||||
glVertex3f( x * r, y * r, z );
|
||||
emitNormal( x, y, nz );
|
||||
glVertex3f( x * ( r + dr ), y * ( r + dr ), z + dz );
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
r += dr;
|
||||
t += dz; // (texture t unused; kept for structural parity)
|
||||
z += dz;
|
||||
}
|
||||
|
||||
(void) t;
|
||||
}
|
||||
|
||||
|
||||
void gluDisk( GLUquadric* q, double inner, double outer, int slices, int loops )
|
||||
{
|
||||
(void) q;
|
||||
(void) inner;
|
||||
(void) outer;
|
||||
(void) slices;
|
||||
(void) loops;
|
||||
GL1_WARN_ONCE( "gluDisk not implemented yet (M4) — geometry dropped" );
|
||||
|
||||
if( slices < 2 || loops < 1 )
|
||||
return;
|
||||
|
||||
// GLU_OUTSIDE: disk normal is +Z; the innermost ring of a full disk
|
||||
// (inner == 0) degenerates its inner vertices at the origin, exactly as
|
||||
// the reference implementation renders it.
|
||||
glNormal3f( 0.0f, 0.0f, 1.0f );
|
||||
|
||||
const float da = (float) ( 2.0 * GLU_PI / slices );
|
||||
const float dr = (float) ( ( outer - inner ) / loops );
|
||||
|
||||
float r1 = (float) inner;
|
||||
|
||||
for( int l = 0; l < loops; l++ )
|
||||
{
|
||||
const float r2 = r1 + dr;
|
||||
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
|
||||
for( int s = 0; s <= slices; s++ )
|
||||
{
|
||||
const float a = ( s == slices ) ? 0.0f : (float) s * da;
|
||||
const float sa = std::sin( a );
|
||||
const float ca = std::cos( a );
|
||||
|
||||
glVertex2f( r2 * sa, r2 * ca );
|
||||
glVertex2f( r1 * sa, r1 * ca );
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
r1 = r2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gluSphere( GLUquadric* q, double radius, int slices, int stacks )
|
||||
{
|
||||
(void) q;
|
||||
(void) radius;
|
||||
(void) slices;
|
||||
(void) stacks;
|
||||
GL1_WARN_ONCE( "gluSphere not implemented yet (M4) — geometry dropped" );
|
||||
|
||||
if( slices < 2 || stacks < 2 )
|
||||
return;
|
||||
|
||||
const float drho = (float) ( GLU_PI / stacks );
|
||||
const float dtheta = (float) ( 2.0 * GLU_PI / slices );
|
||||
const float rad = (float) radius;
|
||||
|
||||
// +Z pole cap (triangle fan).
|
||||
glBegin( GL_TRIANGLE_FAN );
|
||||
glNormal3f( 0.0f, 0.0f, 1.0f );
|
||||
glVertex3f( 0.0f, 0.0f, rad );
|
||||
|
||||
for( int j = 0; j <= slices; j++ )
|
||||
{
|
||||
const float theta = ( j == slices ) ? 0.0f : (float) j * dtheta;
|
||||
const float x = -std::sin( theta ) * std::sin( drho );
|
||||
const float y = std::cos( theta ) * std::sin( drho );
|
||||
const float z = std::cos( drho );
|
||||
|
||||
glNormal3f( x, y, z );
|
||||
glVertex3f( x * rad, y * rad, z * rad );
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
// Intermediate stacks as quad strips.
|
||||
for( int i = 1; i < stacks - 1; i++ )
|
||||
{
|
||||
const float rho = (float) i * drho;
|
||||
|
||||
glBegin( GL_QUAD_STRIP );
|
||||
|
||||
for( int j = 0; j <= slices; j++ )
|
||||
{
|
||||
const float theta = ( j == slices ) ? 0.0f : (float) j * dtheta;
|
||||
|
||||
float x = -std::sin( theta ) * std::sin( rho );
|
||||
float y = std::cos( theta ) * std::sin( rho );
|
||||
float z = std::cos( rho );
|
||||
|
||||
glNormal3f( x, y, z );
|
||||
glVertex3f( x * rad, y * rad, z * rad );
|
||||
|
||||
x = -std::sin( theta ) * std::sin( rho + drho );
|
||||
y = std::cos( theta ) * std::sin( rho + drho );
|
||||
z = std::cos( rho + drho );
|
||||
|
||||
glNormal3f( x, y, z );
|
||||
glVertex3f( x * rad, y * rad, z * rad );
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// -Z pole cap (triangle fan, reverse slice order).
|
||||
glBegin( GL_TRIANGLE_FAN );
|
||||
glNormal3f( 0.0f, 0.0f, -1.0f );
|
||||
glVertex3f( 0.0f, 0.0f, -rad );
|
||||
|
||||
const float rho = (float) GLU_PI - drho;
|
||||
|
||||
for( int j = slices; j >= 0; j-- )
|
||||
{
|
||||
const float theta = ( j == slices ) ? 0.0f : (float) j * dtheta;
|
||||
const float x = -std::sin( theta ) * std::sin( rho );
|
||||
const float y = std::cos( theta ) * std::sin( rho );
|
||||
const float z = std::cos( rho );
|
||||
|
||||
glNormal3f( x, y, z );
|
||||
glVertex3f( x * rad, y * rad, z * rad );
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -101,6 +101,10 @@ void stateBlendFunc( GLenum sfactor, GLenum dfactor )
|
|||
|
||||
void stateLineWidth( GLfloat width )
|
||||
{
|
||||
if( width > 1.0f )
|
||||
GL1_WARN_ONCE( "glLineWidth(%g): browsers clamp line width to 1 — lines render thinner "
|
||||
"than native (known WebGL2 limitation)", (double) width );
|
||||
|
||||
S().lineWidth = width;
|
||||
__real_glLineWidth( width );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Fixed-function-pipeline (FFP) no-op stubs for the WASM 3D-viewer build.
|
||||
*
|
||||
* KiCad's 3D "OpenGL" renderer (under 3d-viewer/3d_rendering/opengl) is pure
|
||||
* GL 1.x fixed-function: immediate mode, display lists, the matrix stack,
|
||||
* FFP lighting/material, client-state vertex arrays and GLU quadrics. None of
|
||||
* those entry points exist in WebGL2 / GLES3.
|
||||
*
|
||||
* On WASM we do NOT render through that renderer — the 3D viewer draws with the
|
||||
* GL-free CPU raytracer (RENDER_3D_RAYTRACE_RAM) and blits the result with a
|
||||
* plain WebGL2 textured quad (see EDA_3D_CANVAS). The fixed-function renderer is
|
||||
* still compiled (it is referenced from several shared files: eda_3d_canvas,
|
||||
* appearance_controls_3D, panel_preview_3d_model, eda_3d_controller), so its FFP
|
||||
* calls must *link*. These no-op definitions satisfy the linker without dragging
|
||||
* in Emscripten's -sLEGACY_GL_EMULATION (which is module-global, ~200 KB, and was
|
||||
* rejected for this project — see docs/features/fork-cleanup/10-3d-viewer.md).
|
||||
* The functions are never executed at runtime; they only need to exist.
|
||||
*
|
||||
* Signatures are taken verbatim from Emscripten's <GL/gl.h> (and the project's
|
||||
* GLU stub <GL/glu.h>) so the compiler validates them against the same
|
||||
* declarations the renderer is built against.
|
||||
*
|
||||
* Only the symbols absent from core WebGL2/GLES3 are stubbed here. Modern entry
|
||||
* points (glDrawArrays, glGenBuffers, glUseProgram, glTexImage2D, …) are provided
|
||||
* by Emscripten's WebGL library and must NOT be redefined.
|
||||
*/
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h> /* resolved to wasm/stubs/GL/glu.h via -I${STUBS_DIR} */
|
||||
|
||||
/* ---- Immediate mode --------------------------------------------------- */
|
||||
void glBegin( GLenum mode ) { (void) mode; }
|
||||
void glEnd( void ) {}
|
||||
void glVertex2f( GLfloat x, GLfloat y ) { (void) x; (void) y; }
|
||||
void glVertex3f( GLfloat x, GLfloat y, GLfloat z ) { (void) x; (void) y; (void) z; }
|
||||
void glVertex3d( GLdouble x, GLdouble y, GLdouble z ) { (void) x; (void) y; (void) z; }
|
||||
void glNormal3f( GLfloat nx, GLfloat ny, GLfloat nz ) { (void) nx; (void) ny; (void) nz; }
|
||||
void glColor3f( GLfloat r, GLfloat g, GLfloat b ) { (void) r; (void) g; (void) b; }
|
||||
void glColor4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) { (void) r; (void) g; (void) b; (void) a; }
|
||||
|
||||
/* ---- Display lists ---------------------------------------------------- */
|
||||
GLuint glGenLists( GLsizei range ) { (void) range; return 1; }
|
||||
void glNewList( GLuint list, GLenum mode ) { (void) list; (void) mode; }
|
||||
void glEndList( void ) {}
|
||||
void glCallList( GLuint list ) { (void) list; }
|
||||
void glDeleteLists( GLuint list, GLsizei range ) { (void) list; (void) range; }
|
||||
GLboolean glIsList( GLuint list ) { (void) list; return GL_FALSE; }
|
||||
|
||||
/* ---- Matrix stack ----------------------------------------------------- */
|
||||
void glMatrixMode( GLenum mode ) { (void) mode; }
|
||||
void glLoadIdentity( void ) {}
|
||||
void glLoadMatrixf( const GLfloat* m ) { (void) m; }
|
||||
void glPushMatrix( void ) {}
|
||||
void glPopMatrix( void ) {}
|
||||
void glTranslatef( GLfloat x, GLfloat y, GLfloat z ) { (void) x; (void) y; (void) z; }
|
||||
void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) { (void) angle; (void) x; (void) y; (void) z; }
|
||||
void glScalef( GLfloat x, GLfloat y, GLfloat z ) { (void) x; (void) y; (void) z; }
|
||||
void glScaled( GLdouble x, GLdouble y, GLdouble z ) { (void) x; (void) y; (void) z; }
|
||||
|
||||
/* ---- Fixed-function lighting / material ------------------------------- */
|
||||
void glShadeModel( GLenum mode ) { (void) mode; }
|
||||
void glLightfv( GLenum light, GLenum pname, const GLfloat* params ) { (void) light; (void) pname; (void) params; }
|
||||
void glLightModeli( GLenum pname, GLint param ) { (void) pname; (void) param; }
|
||||
void glLightModelfv( GLenum pname, const GLfloat* params ) { (void) pname; (void) params; }
|
||||
void glMaterialf( GLenum face, GLenum pname, GLfloat param ) { (void) face; (void) pname; (void) param; }
|
||||
void glMaterialfv( GLenum face, GLenum pname, const GLfloat* params ) { (void) face; (void) pname; (void) params; }
|
||||
void glColorMaterial( GLenum face, GLenum mode ) { (void) face; (void) mode; }
|
||||
|
||||
/* ---- Client-state vertex arrays --------------------------------------- */
|
||||
void glEnableClientState( GLenum cap ) { (void) cap; }
|
||||
void glDisableClientState( GLenum cap ) { (void) cap; }
|
||||
void glClientActiveTexture( GLenum texture ) { (void) texture; }
|
||||
void glVertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid* ptr ) { (void) size; (void) type; (void) stride; (void) ptr; }
|
||||
void glNormalPointer( GLenum type, GLsizei stride, const GLvoid* ptr ) { (void) type; (void) stride; (void) ptr; }
|
||||
void glColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid* ptr ) { (void) size; (void) type; (void) stride; (void) ptr; }
|
||||
void glTexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid* ptr ) { (void) size; (void) type; (void) stride; (void) ptr; }
|
||||
|
||||
/* ---- Fixed-function texture environment ------------------------------- */
|
||||
void glTexEnvf( GLenum target, GLenum pname, GLfloat param ) { (void) target; (void) pname; (void) param; }
|
||||
void glTexEnvi( GLenum target, GLenum pname, GLint param ) { (void) target; (void) pname; (void) param; }
|
||||
void glTexEnvfv( GLenum target, GLenum pname, const GLfloat* params ) { (void) target; (void) pname; (void) params; }
|
||||
|
||||
/* ---- Misc fixed-function state absent from GLES3 ---------------------- */
|
||||
void glAlphaFunc( GLenum func, GLclampf ref ) { (void) func; (void) ref; }
|
||||
void glPolygonMode( GLenum face, GLenum mode ) { (void) face; (void) mode; }
|
||||
void glClearDepth( GLclampd depth ) { (void) depth; }
|
||||
void glPointSize( GLfloat size ) { (void) size; }
|
||||
|
||||
/* ---- GLU quadrics (vias/pads/gizmo) + gluPerspective ------------------ */
|
||||
/* GLUquadric is an opaque/incomplete type; hand back a stable non-null pointer
|
||||
* the renderer can store and pass to the (no-op) quadric calls below. */
|
||||
static int g_dummyQuadric;
|
||||
GLUquadric* gluNewQuadric( void ) { return (GLUquadric*) &g_dummyQuadric; }
|
||||
void gluDeleteQuadric( GLUquadric* q ) { (void) q; }
|
||||
void gluQuadricDrawStyle( GLUquadric* q, GLenum style ) { (void) q; (void) style; }
|
||||
void gluQuadricNormals( GLUquadric* q, GLenum normals ) { (void) q; (void) normals; }
|
||||
void gluCylinder( GLUquadric* q, double base, double top, double height, int slices, int stacks )
|
||||
{ (void) q; (void) base; (void) top; (void) height; (void) slices; (void) stacks; }
|
||||
void gluDisk( GLUquadric* q, double inner, double outer, int slices, int loops )
|
||||
{ (void) q; (void) inner; (void) outer; (void) slices; (void) loops; }
|
||||
void gluSphere( GLUquadric* q, double radius, int slices, int stacks )
|
||||
{ (void) q; (void) radius; (void) slices; (void) stacks; }
|
||||
void gluPerspective( double fovy, double aspect, double zNear, double zFar )
|
||||
{ (void) fovy; (void) aspect; (void) zNear; (void) zFar; }
|
||||
Loading…
Reference in a new issue