Enable 3D viewer in KiCad WASM build
Build the 3D viewer code for WASM instead of stubbing it out. This is simpler to maintain than complex header stubs. Changes: - Enable KICAD_BUILD_3D_VIEWER_WASM=ON in build script - Remove -gsource-map to avoid OOM in wasm-emscripten-finalize - Add OpenGL stubs for fixed-function pipeline (WebGL ES 2.0 only) - Add GLU stub for gluErrorString - Add NNG stub for IPC API (sockets don't work in WASM) - Add PCBnew scripting stub - Expand curl and libgit2 stubs The 3D viewer code compiles but won't render at runtime since OpenGL GAL is disabled and Cairo GAL is used instead. 🤖 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
74a2dc2c0f
commit
898e079ef2
10 changed files with 1017 additions and 7 deletions
2
kicad
2
kicad
|
|
@ -1 +1 @@
|
|||
Subproject commit e6a59ab94a325f5df44bca6f8b7b7aa9d75fbf03
|
||||
Subproject commit 46bb16e86bb7085578298bcc72a261f612dd8196
|
||||
|
|
@ -128,8 +128,10 @@ if [ "${DEBUG_BUILD:-0}" = "1" ] || [ $DEBUG -eq 1 ]; then
|
|||
BUILD_TYPE="Debug"
|
||||
EXTRA_FLAGS="-g -O1 -fexceptions -matomics -mbulk-memory"
|
||||
# -O0 at link time skips wasm-opt (which can OOM on large WASM with debug symbols)
|
||||
LINKER_DEBUG_FLAGS="-O0 -g -gsource-map -fexceptions"
|
||||
log_info "Building KiCad in DEBUG mode (with source maps, -O1 for WASM compatibility)"
|
||||
# NOTE: -gsource-map removed because wasm-emscripten-finalize OOMs on large WASM
|
||||
# with source maps enabled. Keep -g for debug symbols in the WASM.
|
||||
LINKER_DEBUG_FLAGS="-O0 -g -fexceptions"
|
||||
log_info "Building KiCad in DEBUG mode (debug symbols, no source maps due to memory)"
|
||||
else
|
||||
BUILD_TYPE="Release"
|
||||
EXTRA_FLAGS="-O2 -fexceptions -matomics -mbulk-memory"
|
||||
|
|
@ -157,6 +159,19 @@ emar rcs "${STUBS_BUILD}/libgit2_stub.a" "${STUBS_BUILD}/libgit2_stub.o"
|
|||
emcc -c "${STUBS_DIR}/curl_stub.c" -o "${STUBS_BUILD}/curl_stub.o"
|
||||
emar rcs "${STUBS_BUILD}/libcurl_stub.a" "${STUBS_BUILD}/curl_stub.o"
|
||||
|
||||
# Compile GLU stub (for 3D viewer)
|
||||
emcc -c "${STUBS_DIR}/glu_stub.c" -o "${STUBS_BUILD}/glu_stub.o"
|
||||
emar rcs "${STUBS_BUILD}/libglu_stub.a" "${STUBS_BUILD}/glu_stub.o"
|
||||
|
||||
# Compile PCBnew scripting stub (requires wxWidgets headers)
|
||||
WX_CXXFLAGS=$("${WX_BUILD}/wx-config" --cxxflags 2>/dev/null || echo "-I${WX_BUILD}/lib/wx/include/emscripten-unicode-static-3.2 -I${PROJECT_ROOT}/wxwidgets/include")
|
||||
em++ -c ${WX_CXXFLAGS} "${STUBS_DIR}/pcbnew_scripting_stub.cpp" -o "${STUBS_BUILD}/pcbnew_scripting_stub.o"
|
||||
emar rcs "${STUBS_BUILD}/libpcbnew_scripting_stub.a" "${STUBS_BUILD}/pcbnew_scripting_stub.o"
|
||||
|
||||
# Compile NNG stub (IPC API requires NNG but sockets don't work in WASM)
|
||||
emcc -c -I"${STUBS_DIR}" "${STUBS_DIR}/nng_stub.c" -o "${STUBS_BUILD}/nng_stub.o"
|
||||
emar rcs "${STUBS_BUILD}/libnng_stub.a" "${STUBS_BUILD}/nng_stub.o"
|
||||
|
||||
log_info "Stub libraries built"
|
||||
|
||||
# Step 6.2: Replace Emscripten's wasm-opt with stub to bypass asyncify transformation
|
||||
|
|
@ -197,9 +212,9 @@ emcmake cmake "${KICAD_DIR}" \
|
|||
-DCMAKE_MODULE_PATH="${WASM_LAYER}/cmake" \
|
||||
-DSYSROOT="${SYSROOT}" \
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
-DCMAKE_CXX_FLAGS="${EXTRA_FLAGS} -pthread -sUSE_ZLIB=1 -DKICAD_USE_PLATFORM_WASM=1 -I${SYSROOT}/include" \
|
||||
-DCMAKE_C_FLAGS="${EXTRA_FLAGS} -pthread -sUSE_ZLIB=1 -I${SYSROOT}/include" \
|
||||
-DCMAKE_EXE_LINKER_FLAGS="${LINKER_DEBUG_FLAGS} -pthread -sUSE_ZLIB=1 -sASYNCIFY=1 -sASYNCIFY_STACK_SIZE=65536 -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE='navigator.hardwareConcurrency' -sPTHREAD_POOL_SIZE_STRICT=0 -sALLOW_MEMORY_GROWTH=1 -sINITIAL_MEMORY=256MB -sMAXIMUM_MEMORY=4GB -sEXPORTED_RUNTIME_METHODS=['ccall','cwrap','UTF8ToString','stringToUTF8','lengthBytesUTF8'] -L${SYSROOT}/lib ${STUBS_BUILD}/libgit2_stub.a ${STUBS_BUILD}/libcurl_stub.a" \
|
||||
-DCMAKE_CXX_FLAGS="${EXTRA_FLAGS} -pthread -sUSE_ZLIB=1 -DKICAD_USE_PLATFORM_WASM=1 -I${SYSROOT}/include -I${STUBS_DIR}" \
|
||||
-DCMAKE_C_FLAGS="${EXTRA_FLAGS} -pthread -sUSE_ZLIB=1 -I${SYSROOT}/include -I${STUBS_DIR}" \
|
||||
-DCMAKE_EXE_LINKER_FLAGS="${LINKER_DEBUG_FLAGS} -pthread -sUSE_ZLIB=1 -sASYNCIFY=1 -sASYNCIFY_STACK_SIZE=65536 -sUSE_PTHREADS=1 -sPTHREAD_POOL_SIZE='navigator.hardwareConcurrency' -sPTHREAD_POOL_SIZE_STRICT=0 -sALLOW_MEMORY_GROWTH=1 -sINITIAL_MEMORY=256MB -sMAXIMUM_MEMORY=4GB -sEXPORTED_RUNTIME_METHODS=['ccall','cwrap','UTF8ToString','stringToUTF8','lengthBytesUTF8'] -L${SYSROOT}/lib ${STUBS_BUILD}/libgit2_stub.a ${STUBS_BUILD}/libcurl_stub.a ${STUBS_BUILD}/libglu_stub.a ${STUBS_BUILD}/libpcbnew_scripting_stub.a ${STUBS_BUILD}/libnng_stub.a" \
|
||||
-DCMAKE_PREFIX_PATH="${SYSROOT};${WX_BUILD}" \
|
||||
-DwxWidgets_CONFIG_EXECUTABLE="${WX_BUILD}/wx-config" \
|
||||
\
|
||||
|
|
@ -207,6 +222,8 @@ emcmake cmake "${KICAD_DIR}" \
|
|||
-DKICAD_SPICE=OFF \
|
||||
-DKICAD_USE_EGL=OFF \
|
||||
-DKICAD_USE_BUNDLED_GLEW=ON \
|
||||
-DKICAD_BUILD_3D_VIEWER_WASM=ON \
|
||||
-DKICAD_IPC_API=ON \
|
||||
\
|
||||
-DZSTD_ROOT="${SYSROOT}" \
|
||||
-DZSTD_INCLUDE_DIR="${SYSROOT}/include" \
|
||||
|
|
@ -227,6 +244,7 @@ emcmake cmake "${KICAD_DIR}" \
|
|||
-DProtobuf_INCLUDE_DIR="${SYSROOT}/include" \
|
||||
-DProtobuf_LIBRARY="${SYSROOT}/lib/libprotobuf.a" \
|
||||
-DProtobuf_LITE_LIBRARY="${SYSROOT}/lib/libprotobuf-lite.a" \
|
||||
-DProtobuf_PROTOC_EXECUTABLE="${SYSROOT}/bin/protoc" \
|
||||
-DODBC_CONFIG:STRING="stub-for-wasm" \
|
||||
-DODBCLIB:STRING="" \
|
||||
-DODBC_CFLAGS:STRING="" \
|
||||
|
|
@ -238,7 +256,6 @@ emcmake cmake "${KICAD_DIR}" \
|
|||
|
||||
# Step 8: Build pcbnew target
|
||||
log_info "Building pcbnew..."
|
||||
# JOBS is set in env.sh (default: 1 for sequential builds, use -j N to override)
|
||||
emmake make -j${JOBS} pcbnew
|
||||
|
||||
# Step 9: Create stamp file
|
||||
|
|
|
|||
|
|
@ -2,8 +2,68 @@
|
|||
* Network operations need to go through JavaScript fetch API
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef void CURL;
|
||||
typedef void CURLM;
|
||||
typedef int CURLcode;
|
||||
typedef int CURLoption;
|
||||
typedef int CURLINFO;
|
||||
|
||||
#define CURLE_OK 0
|
||||
#define CURLE_UNSUPPORTED_PROTOCOL 1
|
||||
|
||||
/* Version info */
|
||||
const char* curl_version(void) {
|
||||
return "stub-wasm/0.0 (no network in browser)";
|
||||
}
|
||||
|
||||
/* Easy interface */
|
||||
CURL* curl_easy_init(void) {
|
||||
return NULL; /* No curl in WASM */
|
||||
}
|
||||
|
||||
void curl_easy_cleanup(CURL *curl) {
|
||||
(void)curl;
|
||||
}
|
||||
|
||||
CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...) {
|
||||
(void)curl;
|
||||
(void)option;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
CURLcode curl_easy_perform(CURL *curl) {
|
||||
(void)curl;
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
|
||||
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...) {
|
||||
(void)curl;
|
||||
(void)info;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
const char* curl_easy_strerror(CURLcode code) {
|
||||
(void)code;
|
||||
return "Network operations not available in browser";
|
||||
}
|
||||
|
||||
void curl_easy_reset(CURL *curl) {
|
||||
(void)curl;
|
||||
}
|
||||
|
||||
char* curl_easy_escape(CURL *curl, const char *string, int length) {
|
||||
(void)curl;
|
||||
(void)string;
|
||||
(void)length;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void curl_free(void *p) {
|
||||
(void)p;
|
||||
}
|
||||
|
||||
CURLcode curl_global_init(long flags) {
|
||||
(void)flags;
|
||||
|
|
@ -13,3 +73,28 @@ CURLcode curl_global_init(long flags) {
|
|||
void curl_global_cleanup(void) {
|
||||
/* Nothing to clean up */
|
||||
}
|
||||
|
||||
/* Multi interface (for async) */
|
||||
CURLM* curl_multi_init(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void curl_multi_cleanup(CURLM *multi) {
|
||||
(void)multi;
|
||||
}
|
||||
|
||||
/* Slist */
|
||||
struct curl_slist {
|
||||
char *data;
|
||||
struct curl_slist *next;
|
||||
};
|
||||
|
||||
struct curl_slist* curl_slist_append(struct curl_slist *list, const char *string) {
|
||||
(void)list;
|
||||
(void)string;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void curl_slist_free_all(struct curl_slist *list) {
|
||||
(void)list;
|
||||
}
|
||||
|
|
|
|||
509
wasm/stubs/gl_canvas_stub.cpp
Normal file
509
wasm/stubs/gl_canvas_stub.cpp
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* OpenGL Canvas stubs for KiCad WASM build
|
||||
* OpenGL GAL is not available in WASM (uses Cairo only).
|
||||
* This stub provides typeinfo and methods for dynamic_cast to work.
|
||||
*/
|
||||
|
||||
#include <gal/hidpi_gl_canvas.h>
|
||||
#include <gal/hidpi_gl_3D_canvas.h>
|
||||
#include <3d_rendering/raytracing/render_3d_raytrace_gl.h>
|
||||
|
||||
//=============================================================================
|
||||
// Fixed-function OpenGL stubs for WebGL compatibility
|
||||
// WebGL only supports OpenGL ES 2.0/3.0 which doesn't have these functions
|
||||
//=============================================================================
|
||||
|
||||
extern "C" {
|
||||
|
||||
void glLoadMatrixf( const float* m )
|
||||
{
|
||||
(void)m;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glPushMatrix()
|
||||
{
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glPopMatrix()
|
||||
{
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glColor4f( float r, float g, float b, float a )
|
||||
{
|
||||
(void)r; (void)g; (void)b; (void)a;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glTranslatef( float x, float y, float z )
|
||||
{
|
||||
(void)x; (void)y; (void)z;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glScalef( float x, float y, float z )
|
||||
{
|
||||
(void)x; (void)y; (void)z;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glRotatef( float angle, float x, float y, float z )
|
||||
{
|
||||
(void)angle; (void)x; (void)y; (void)z;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glEnableClientState( unsigned int cap )
|
||||
{
|
||||
(void)cap;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glDisableClientState( unsigned int cap )
|
||||
{
|
||||
(void)cap;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glPointSize( float size )
|
||||
{
|
||||
(void)size;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glVertex3f( float x, float y, float z )
|
||||
{
|
||||
(void)x; (void)y; (void)z;
|
||||
// Immediate mode not available in WebGL
|
||||
}
|
||||
|
||||
void glBegin( unsigned int mode )
|
||||
{
|
||||
(void)mode;
|
||||
// Immediate mode not available in WebGL
|
||||
}
|
||||
|
||||
void glEnd()
|
||||
{
|
||||
// Immediate mode not available in WebGL
|
||||
}
|
||||
|
||||
void glColorMaterial( unsigned int face, unsigned int mode )
|
||||
{
|
||||
(void)face; (void)mode;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glNormalPointer( unsigned int type, int stride, const void* pointer )
|
||||
{
|
||||
(void)type; (void)stride; (void)pointer;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glColorPointer( int size, unsigned int type, int stride, const void* pointer )
|
||||
{
|
||||
(void)size; (void)type; (void)stride; (void)pointer;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glTexCoordPointer( int size, unsigned int type, int stride, const void* pointer )
|
||||
{
|
||||
(void)size; (void)type; (void)stride; (void)pointer;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glVertexPointer( int size, unsigned int type, int stride, const void* pointer )
|
||||
{
|
||||
(void)size; (void)type; (void)stride; (void)pointer;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glMaterialfv( unsigned int face, unsigned int pname, const float* params )
|
||||
{
|
||||
(void)face; (void)pname; (void)params;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glMaterialf( unsigned int face, unsigned int pname, float param )
|
||||
{
|
||||
(void)face; (void)pname; (void)param;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glLightfv( unsigned int light, unsigned int pname, const float* params )
|
||||
{
|
||||
(void)light; (void)pname; (void)params;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glLightModelfv( unsigned int pname, const float* params )
|
||||
{
|
||||
(void)pname; (void)params;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glNormal3f( float nx, float ny, float nz )
|
||||
{
|
||||
(void)nx; (void)ny; (void)nz;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glTexCoord2f( float s, float t )
|
||||
{
|
||||
(void)s; (void)t;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glMatrixMode( unsigned int mode )
|
||||
{
|
||||
(void)mode;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glLoadIdentity()
|
||||
{
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glOrtho( double left, double right, double bottom, double top, double nearVal, double farVal )
|
||||
{
|
||||
(void)left; (void)right; (void)bottom; (void)top; (void)nearVal; (void)farVal;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glFrustum( double left, double right, double bottom, double top, double nearVal, double farVal )
|
||||
{
|
||||
(void)left; (void)right; (void)bottom; (void)top; (void)nearVal; (void)farVal;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glMultMatrixf( const float* m )
|
||||
{
|
||||
(void)m;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glShadeModel( unsigned int mode )
|
||||
{
|
||||
(void)mode;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glTexEnvfv( unsigned int target, unsigned int pname, const float* params )
|
||||
{
|
||||
(void)target; (void)pname; (void)params;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glTexEnvf( unsigned int target, unsigned int pname, float param )
|
||||
{
|
||||
(void)target; (void)pname; (void)param;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glTexEnvi( unsigned int target, unsigned int pname, int param )
|
||||
{
|
||||
(void)target; (void)pname; (void)param;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glLightModeli( unsigned int pname, int param )
|
||||
{
|
||||
(void)pname; (void)param;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
// Display lists - not available in WebGL
|
||||
unsigned char glIsList( unsigned int list )
|
||||
{
|
||||
(void)list;
|
||||
return 0; // Always return false - no display lists in WebGL
|
||||
}
|
||||
|
||||
void glDeleteLists( unsigned int list, int range )
|
||||
{
|
||||
(void)list; (void)range;
|
||||
// Display lists not available in WebGL
|
||||
}
|
||||
|
||||
unsigned int glGenLists( int range )
|
||||
{
|
||||
(void)range;
|
||||
return 0; // Return 0 to indicate failure - no display lists in WebGL
|
||||
}
|
||||
|
||||
void glNewList( unsigned int list, unsigned int mode )
|
||||
{
|
||||
(void)list; (void)mode;
|
||||
// Display lists not available in WebGL
|
||||
}
|
||||
|
||||
void glEndList()
|
||||
{
|
||||
// Display lists not available in WebGL
|
||||
}
|
||||
|
||||
void glCallList( unsigned int list )
|
||||
{
|
||||
(void)list;
|
||||
// Display lists not available in WebGL
|
||||
}
|
||||
|
||||
void glCallLists( int n, unsigned int type, const void* lists )
|
||||
{
|
||||
(void)n; (void)type; (void)lists;
|
||||
// Display lists not available in WebGL
|
||||
}
|
||||
|
||||
// More fixed-function pipeline functions
|
||||
void glColor3f( float r, float g, float b )
|
||||
{
|
||||
(void)r; (void)g; (void)b;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glColor3fv( const float* v )
|
||||
{
|
||||
(void)v;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glColor4fv( const float* v )
|
||||
{
|
||||
(void)v;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glVertex2f( float x, float y )
|
||||
{
|
||||
(void)x; (void)y;
|
||||
// Immediate mode not available in WebGL
|
||||
}
|
||||
|
||||
void glVertex3fv( const float* v )
|
||||
{
|
||||
(void)v;
|
||||
// Immediate mode not available in WebGL
|
||||
}
|
||||
|
||||
void glNormal3fv( const float* v )
|
||||
{
|
||||
(void)v;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glRectf( float x1, float y1, float x2, float y2 )
|
||||
{
|
||||
(void)x1; (void)y1; (void)x2; (void)y2;
|
||||
// Immediate mode not available in WebGL
|
||||
}
|
||||
|
||||
void glLineWidth( float width )
|
||||
{
|
||||
(void)width;
|
||||
// Note: WebGL has limited line width support
|
||||
}
|
||||
|
||||
void glAlphaFunc( unsigned int func, float ref )
|
||||
{
|
||||
(void)func; (void)ref;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glClientActiveTexture( unsigned int texture )
|
||||
{
|
||||
(void)texture;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glScaled( double x, double y, double z )
|
||||
{
|
||||
(void)x; (void)y; (void)z;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glPolygonMode( unsigned int face, unsigned int mode )
|
||||
{
|
||||
(void)face; (void)mode;
|
||||
// Not available in WebGL ES
|
||||
}
|
||||
|
||||
void glClipPlane( unsigned int plane, const double* equation )
|
||||
{
|
||||
(void)plane; (void)equation;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glFogf( unsigned int pname, float param )
|
||||
{
|
||||
(void)pname; (void)param;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glFogfv( unsigned int pname, const float* params )
|
||||
{
|
||||
(void)pname; (void)params;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
void glFogi( unsigned int pname, int param )
|
||||
{
|
||||
(void)pname; (void)param;
|
||||
// Fixed-function pipeline not available in WebGL
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
//=============================================================================
|
||||
// HIDPI_GL_CANVAS stub implementation
|
||||
//=============================================================================
|
||||
|
||||
HIDPI_GL_CANVAS::HIDPI_GL_CANVAS( const KIGFX::VC_SETTINGS& aSettings, wxWindow* aParent,
|
||||
const wxGLAttributes& aGLAttribs, wxWindowID aId,
|
||||
const wxPoint& aPos, const wxSize& aSize, long aStyle,
|
||||
const wxString& aName, const wxPalette& aPalette ) :
|
||||
wxGLCanvas( aParent, aGLAttribs, aId, aPos, aSize, aStyle, aName, aPalette ),
|
||||
m_settings( aSettings )
|
||||
{
|
||||
// Not used in WASM - OpenGL is disabled
|
||||
}
|
||||
|
||||
wxSize HIDPI_GL_CANVAS::GetNativePixelSize() const
|
||||
{
|
||||
return wxSize( 0, 0 );
|
||||
}
|
||||
|
||||
wxPoint HIDPI_GL_CANVAS::GetNativePosition( const wxPoint& aPoint ) const
|
||||
{
|
||||
return aPoint;
|
||||
}
|
||||
|
||||
double HIDPI_GL_CANVAS::GetScaleFactor() const
|
||||
{
|
||||
return 1.0; // No HiDPI scaling in WASM stub
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// HIDPI_GL_3D_CANVAS stub implementation
|
||||
//=============================================================================
|
||||
|
||||
const float HIDPI_GL_3D_CANVAS::m_delta_move_step_factor = 0.7f;
|
||||
|
||||
HIDPI_GL_3D_CANVAS::HIDPI_GL_3D_CANVAS( const KIGFX::VC_SETTINGS& aVcSettings, CAMERA& aCamera,
|
||||
wxWindow* aParent, const wxGLAttributes& aGLAttribs,
|
||||
wxWindowID aId, const wxPoint& aPos, const wxSize& aSize,
|
||||
long aStyle, const wxString& aName,
|
||||
const wxPalette& aPalette ) :
|
||||
HIDPI_GL_CANVAS( aVcSettings, aParent, aGLAttribs, aId, aPos, aSize, aStyle, aName, aPalette ),
|
||||
m_camera( aCamera )
|
||||
{
|
||||
m_mouse_is_moving = false;
|
||||
m_mouse_was_moved = false;
|
||||
m_camera_is_moving = false;
|
||||
// Not used in WASM - 3D viewer uses RAM raytracer
|
||||
}
|
||||
|
||||
void HIDPI_GL_3D_CANVAS::OnMouseMoveCamera( wxMouseEvent& event )
|
||||
{
|
||||
(void)event;
|
||||
// Not used in WASM
|
||||
}
|
||||
|
||||
void HIDPI_GL_3D_CANVAS::OnMouseWheelCamera( wxMouseEvent& event, bool aPan )
|
||||
{
|
||||
(void)event;
|
||||
(void)aPan;
|
||||
// Not used in WASM
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// RENDER_3D_RAYTRACE_GL stub implementation
|
||||
//=============================================================================
|
||||
|
||||
RENDER_3D_RAYTRACE_GL::RENDER_3D_RAYTRACE_GL( EDA_3D_CANVAS* aCanvas, BOARD_ADAPTER& aAdapter,
|
||||
CAMERA& aCamera ) :
|
||||
RENDER_3D_RAYTRACE_BASE( aAdapter, aCamera )
|
||||
{
|
||||
(void)aCanvas;
|
||||
m_openglSupportsVertexBufferObjects = false;
|
||||
m_pboId = 0;
|
||||
m_pboDataSize = 0;
|
||||
// Not used in WASM - uses RAM raytracer instead
|
||||
}
|
||||
|
||||
RENDER_3D_RAYTRACE_GL::~RENDER_3D_RAYTRACE_GL()
|
||||
{
|
||||
}
|
||||
|
||||
void RENDER_3D_RAYTRACE_GL::SetCurWindowSize( const wxSize& aSize )
|
||||
{
|
||||
(void)aSize;
|
||||
// Not used in WASM
|
||||
}
|
||||
|
||||
bool RENDER_3D_RAYTRACE_GL::Redraw( bool aIsMoving, REPORTER* aStatusReporter,
|
||||
REPORTER* aWarningReporter )
|
||||
{
|
||||
(void)aIsMoving;
|
||||
(void)aStatusReporter;
|
||||
(void)aWarningReporter;
|
||||
return false; // Not used in WASM
|
||||
}
|
||||
|
||||
void RENDER_3D_RAYTRACE_GL::initPbo()
|
||||
{
|
||||
// Not used in WASM
|
||||
}
|
||||
|
||||
void RENDER_3D_RAYTRACE_GL::deletePbo()
|
||||
{
|
||||
// Not used in WASM
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// NavLib/3DConnexion SpaceMouse plugin stubs
|
||||
// These are for 3D mouse support which is not available in WASM
|
||||
//=============================================================================
|
||||
|
||||
// Define empty implementation classes to satisfy unique_ptr
|
||||
class NL_3D_VIEWER_PLUGIN_IMPL {};
|
||||
class NL_FOOTPRINT_PROPERTIES_PLUGIN_IMPL {};
|
||||
|
||||
#include <3d_navlib/nl_3d_viewer_plugin.h>
|
||||
#include <3d_navlib/nl_footprint_properties_plugin.h>
|
||||
|
||||
NL_3D_VIEWER_PLUGIN::NL_3D_VIEWER_PLUGIN( EDA_3D_CANVAS* aViewport ) :
|
||||
m_impl( nullptr )
|
||||
{
|
||||
(void)aViewport;
|
||||
// SpaceMouse not available in WASM
|
||||
}
|
||||
|
||||
NL_3D_VIEWER_PLUGIN::~NL_3D_VIEWER_PLUGIN()
|
||||
{
|
||||
}
|
||||
|
||||
void NL_3D_VIEWER_PLUGIN::SetFocus( bool aFocus )
|
||||
{
|
||||
(void)aFocus;
|
||||
// SpaceMouse not available in WASM
|
||||
}
|
||||
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN::NL_FOOTPRINT_PROPERTIES_PLUGIN( EDA_3D_CANVAS* aViewport ) :
|
||||
m_impl( nullptr )
|
||||
{
|
||||
(void)aViewport;
|
||||
// SpaceMouse not available in WASM
|
||||
}
|
||||
|
||||
NL_FOOTPRINT_PROPERTIES_PLUGIN::~NL_FOOTPRINT_PROPERTIES_PLUGIN()
|
||||
{
|
||||
}
|
||||
|
||||
void NL_FOOTPRINT_PROPERTIES_PLUGIN::SetFocus( bool aFocus )
|
||||
{
|
||||
(void)aFocus;
|
||||
// SpaceMouse not available in WASM
|
||||
}
|
||||
44
wasm/stubs/glu_stub.c
Normal file
44
wasm/stubs/glu_stub.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* GLU stubs for WebAssembly builds
|
||||
* GLU is not available in WebGL, these stubs prevent link errors.
|
||||
* The gizmo won't render but the 3D view should work with LEGACY_GL_EMULATION.
|
||||
*/
|
||||
|
||||
typedef struct GLUquadric GLUquadric;
|
||||
typedef struct GLUtesselator GLUtesselator;
|
||||
typedef double GLdouble;
|
||||
typedef void (*_GLUfuncptr)(void);
|
||||
|
||||
/* Quadric stubs */
|
||||
GLUquadric* gluNewQuadric(void) { return (GLUquadric*)0; }
|
||||
void gluDeleteQuadric(GLUquadric* q) { (void)q; }
|
||||
void gluQuadricDrawStyle(GLUquadric* q, int s) { (void)q; (void)s; }
|
||||
void gluQuadricNormals(GLUquadric* q, int n) { (void)q; (void)n; }
|
||||
void gluCylinder(GLUquadric* q, double b, double t, double h, int sl, int st) {
|
||||
(void)q; (void)b; (void)t; (void)h; (void)sl; (void)st;
|
||||
}
|
||||
void gluDisk(GLUquadric* q, double i, double o, int sl, int lp) {
|
||||
(void)q; (void)i; (void)o; (void)sl; (void)lp;
|
||||
}
|
||||
void gluSphere(GLUquadric* q, double r, int sl, int st) {
|
||||
(void)q; (void)r; (void)sl; (void)st;
|
||||
}
|
||||
void gluPerspective(double fovy, double aspect, double zNear, double zFar) {
|
||||
(void)fovy; (void)aspect; (void)zNear; (void)zFar;
|
||||
}
|
||||
|
||||
/* Tessellation stubs */
|
||||
GLUtesselator* gluNewTess(void) { return (GLUtesselator*)0; }
|
||||
void gluDeleteTess(GLUtesselator* t) { (void)t; }
|
||||
void gluTessBeginPolygon(GLUtesselator* t, void* d) { (void)t; (void)d; }
|
||||
void gluTessEndPolygon(GLUtesselator* t) { (void)t; }
|
||||
void gluTessBeginContour(GLUtesselator* t) { (void)t; }
|
||||
void gluTessEndContour(GLUtesselator* t) { (void)t; }
|
||||
void gluTessVertex(GLUtesselator* t, GLdouble* l, void* d) { (void)t; (void)l; (void)d; }
|
||||
void gluTessNormal(GLUtesselator* t, GLdouble x, GLdouble y, GLdouble z) { (void)t; (void)x; (void)y; (void)z; }
|
||||
void gluTessCallback(GLUtesselator* t, unsigned int w, _GLUfuncptr f) { (void)t; (void)w; (void)f; }
|
||||
void gluTessProperty(GLUtesselator* t, unsigned int w, GLdouble v) { (void)t; (void)w; (void)v; }
|
||||
void gluGetTessProperty(GLUtesselator* t, unsigned int w, GLdouble* d) { (void)t; (void)w; (void)d; }
|
||||
|
||||
/* Error string stub */
|
||||
static const unsigned char glu_error_str[] = "GLU stub error";
|
||||
const unsigned char* gluErrorString(unsigned int e) { (void)e; return glu_error_str; }
|
||||
|
|
@ -62,3 +62,213 @@ int git_oid_cmp(const void *a, const void *b) {
|
|||
(void)b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Index operations */
|
||||
int git_repository_index(void **out, void *repo) {
|
||||
(void)repo;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_index_add_bypath(void *index, const char *path) {
|
||||
(void)index;
|
||||
(void)path;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_index_write(void *index) {
|
||||
(void)index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_index_write_tree(void *out, void *index) {
|
||||
(void)out;
|
||||
(void)index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void git_index_free(void *index) {
|
||||
(void)index;
|
||||
}
|
||||
|
||||
/* Reference name to ID */
|
||||
int git_reference_name_to_id(void *out, void *repo, const char *name) {
|
||||
(void)out;
|
||||
(void)repo;
|
||||
(void)name;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Commit operations */
|
||||
int git_commit_lookup(void **out, void *repo, const void *id) {
|
||||
(void)repo;
|
||||
(void)id;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_commit_tree(void **out, const void *commit) {
|
||||
(void)commit;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_commit_create(void *id, void *repo, const char *update_ref,
|
||||
const void *author, const void *committer,
|
||||
const char *encoding, const char *message,
|
||||
const void *tree, size_t parent_count, const void **parents) {
|
||||
(void)id; (void)repo; (void)update_ref;
|
||||
(void)author; (void)committer;
|
||||
(void)encoding; (void)message;
|
||||
(void)tree; (void)parent_count; (void)parents;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void git_commit_free(void *commit) {
|
||||
(void)commit;
|
||||
}
|
||||
|
||||
/* Tree operations */
|
||||
int git_tree_lookup(void **out, void *repo, const void *id) {
|
||||
(void)repo;
|
||||
(void)id;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void git_tree_free(void *tree) {
|
||||
(void)tree;
|
||||
}
|
||||
|
||||
/* Diff operations */
|
||||
int git_diff_tree_to_tree(void **diff, void *repo, void *old_tree, void *new_tree, const void *opts) {
|
||||
(void)repo;
|
||||
(void)old_tree;
|
||||
(void)new_tree;
|
||||
(void)opts;
|
||||
*diff = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t git_diff_num_deltas(const void *diff) {
|
||||
(void)diff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_diff_free(void *diff) {
|
||||
(void)diff;
|
||||
}
|
||||
|
||||
/* Signature operations */
|
||||
int git_signature_now(void **out, const char *name, const char *email) {
|
||||
(void)name;
|
||||
(void)email;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void git_signature_free(void *sig) {
|
||||
(void)sig;
|
||||
}
|
||||
|
||||
/* Additional functions needed by local_history.cpp */
|
||||
|
||||
char* git_oid_tostr_s(const void *oid) {
|
||||
(void)oid;
|
||||
return ""; /* Return empty string - static buffer not needed for stub */
|
||||
}
|
||||
|
||||
int git_diff_tree_to_index(void **diff, void *repo, void *old_tree, void *index, const void *opts) {
|
||||
(void)repo;
|
||||
(void)old_tree;
|
||||
(void)index;
|
||||
(void)opts;
|
||||
*diff = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const void* git_diff_get_delta(const void *diff, size_t idx) {
|
||||
(void)diff;
|
||||
(void)idx;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int git_patch_from_diff(void **out, void *diff, size_t idx) {
|
||||
(void)diff;
|
||||
(void)idx;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_patch_line_stats(size_t *total_context, size_t *total_additions, size_t *total_deletions, const void *patch) {
|
||||
(void)patch;
|
||||
if (total_context) *total_context = 0;
|
||||
if (total_additions) *total_additions = 0;
|
||||
if (total_deletions) *total_deletions = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_patch_free(void *patch) {
|
||||
(void)patch;
|
||||
}
|
||||
|
||||
int git_repository_init(void **out, const char *path, unsigned int is_bare) {
|
||||
(void)path;
|
||||
(void)is_bare;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_reference_lookup(void **out, void *repo, const char *name) {
|
||||
(void)repo;
|
||||
(void)name;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_object_lookup(void **out, void *repo, const void *id, int type) {
|
||||
(void)repo;
|
||||
(void)id;
|
||||
(void)type;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_tag_create_lightweight(void *oid, void *repo, const char *tag_name, const void *target, int force) {
|
||||
(void)oid;
|
||||
(void)repo;
|
||||
(void)tag_name;
|
||||
(void)target;
|
||||
(void)force;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void git_object_free(void *object) {
|
||||
(void)object;
|
||||
}
|
||||
|
||||
int git_reference_delete(void *ref) {
|
||||
(void)ref;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Git config operations */
|
||||
int git_config_open_default(void **out) {
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int git_config_get_entry(void **out, const void *cfg, const char *name) {
|
||||
(void)cfg;
|
||||
(void)name;
|
||||
*out = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void git_config_entry_free(void *entry) {
|
||||
(void)entry;
|
||||
}
|
||||
|
||||
void git_config_free(void *cfg) {
|
||||
(void)cfg;
|
||||
}
|
||||
|
|
|
|||
47
wasm/stubs/nng/nng.h
Normal file
47
wasm/stubs/nng/nng.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* NNG stub header for KiCad WASM build
|
||||
* Socket-based IPC is not supported in browsers, so we provide stub implementations
|
||||
* that compile but don't do anything.
|
||||
*/
|
||||
|
||||
#ifndef NNG_NNG_H
|
||||
#define NNG_NNG_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Error codes
|
||||
#define NNG_ETIMEDOUT 5
|
||||
#define NNG_ECLOSED 6
|
||||
#define NNG_ENOENT 7
|
||||
|
||||
// Options
|
||||
#define NNG_OPT_RECVTIMEO "recv-timeout"
|
||||
|
||||
// Flags
|
||||
#define NNG_FLAG_ALLOC 1
|
||||
|
||||
// Opaque types
|
||||
typedef struct nng_socket_s { int id; } nng_socket;
|
||||
typedef struct nng_listener_s { int id; } nng_listener;
|
||||
typedef int nng_duration;
|
||||
|
||||
// NNG function stubs - all return error codes indicating "not supported"
|
||||
int nng_rep0_open(nng_socket *s);
|
||||
int nng_listener_create(nng_listener *l, nng_socket s, const char *url);
|
||||
int nng_socket_set_ms(nng_socket s, const char *opt, nng_duration dur);
|
||||
int nng_listener_start(nng_listener l, int flags);
|
||||
int nng_recv(nng_socket s, void *data, size_t *sizep, int flags);
|
||||
int nng_send(nng_socket s, void *data, size_t size, int flags);
|
||||
int nng_close(nng_socket s);
|
||||
void nng_free(void *ptr, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NNG_NNG_H
|
||||
12
wasm/stubs/nng/protocol/reqrep0/rep.h
Normal file
12
wasm/stubs/nng/protocol/reqrep0/rep.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* NNG REP protocol stub header for KiCad WASM build
|
||||
*/
|
||||
|
||||
#ifndef NNG_PROTOCOL_REQREP0_REP_H
|
||||
#define NNG_PROTOCOL_REQREP0_REP_H
|
||||
|
||||
#include "../../nng.h"
|
||||
|
||||
// nng_rep0_open is already declared in nng.h
|
||||
|
||||
#endif // NNG_PROTOCOL_REQREP0_REP_H
|
||||
66
wasm/stubs/nng_stub.c
Normal file
66
wasm/stubs/nng_stub.c
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* NNG stub implementation for KiCad WASM build
|
||||
* Socket-based IPC is not supported in browsers.
|
||||
* These stubs allow the code to compile but return errors indicating unsupported.
|
||||
*/
|
||||
|
||||
#include "nng/nng.h"
|
||||
|
||||
// All NNG operations fail in WASM since sockets aren't available
|
||||
// Using NNG_ENOENT as a generic "not available" error
|
||||
|
||||
int nng_rep0_open(nng_socket *s) {
|
||||
if (s) {
|
||||
s->id = -1;
|
||||
}
|
||||
return NNG_ENOENT;
|
||||
}
|
||||
|
||||
int nng_listener_create(nng_listener *l, nng_socket s, const char *url) {
|
||||
(void)s;
|
||||
(void)url;
|
||||
if (l) {
|
||||
l->id = -1;
|
||||
}
|
||||
return NNG_ENOENT;
|
||||
}
|
||||
|
||||
int nng_socket_set_ms(nng_socket s, const char *opt, nng_duration dur) {
|
||||
(void)s;
|
||||
(void)opt;
|
||||
(void)dur;
|
||||
return NNG_ENOENT;
|
||||
}
|
||||
|
||||
int nng_listener_start(nng_listener l, int flags) {
|
||||
(void)l;
|
||||
(void)flags;
|
||||
return NNG_ENOENT;
|
||||
}
|
||||
|
||||
int nng_recv(nng_socket s, void *data, size_t *sizep, int flags) {
|
||||
(void)s;
|
||||
(void)data;
|
||||
(void)sizep;
|
||||
(void)flags;
|
||||
return NNG_ENOENT;
|
||||
}
|
||||
|
||||
int nng_send(nng_socket s, void *data, size_t size, int flags) {
|
||||
(void)s;
|
||||
(void)data;
|
||||
(void)size;
|
||||
(void)flags;
|
||||
return NNG_ENOENT;
|
||||
}
|
||||
|
||||
int nng_close(nng_socket s) {
|
||||
(void)s;
|
||||
return 0; // Close always succeeds
|
||||
}
|
||||
|
||||
void nng_free(void *ptr, size_t size) {
|
||||
(void)ptr;
|
||||
(void)size;
|
||||
// Nothing to free in stub
|
||||
}
|
||||
20
wasm/stubs/pcbnew_scripting_stub.cpp
Normal file
20
wasm/stubs/pcbnew_scripting_stub.cpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* PCBnew scripting stubs for WebAssembly builds
|
||||
* Python scripting is disabled in WASM, these stubs prevent link errors.
|
||||
*/
|
||||
|
||||
#include <wx/string.h>
|
||||
|
||||
void pcbnewGetScriptsSearchPaths( wxString& aNames )
|
||||
{
|
||||
aNames = wxT("(Scripting disabled in WASM build)");
|
||||
}
|
||||
|
||||
void pcbnewGetUnloadableScriptNames( wxString& aNames )
|
||||
{
|
||||
aNames = wxEmptyString;
|
||||
}
|
||||
|
||||
void pcbnewGetWizardsBackTrace( wxString& aTrace )
|
||||
{
|
||||
aTrace = wxEmptyString;
|
||||
}
|
||||
Loading…
Reference in a new issue