Skip to content

simple SDL program throws JavaScript exception: SDL2.ctx is null #21716

@bottle2

Description

@bottle2

good night

when I $ emrun random.html, both inside Firefox and Edge on Windows 10, the HTML shell says "Exception thrown, see JavaScript console".

then I open console. I hit the browser's reload webpage button while holding SHIFT. it is impossible to refresh the webpage using keyboard for some reason.

the console says:

Uncaught TypeError: SDL2.ctx is null
    75510 http://localhost:6931/index.html:812
    runMainThreadEmAsm http://localhost:6931/index.html:5159
    _emscripten_asm_const_int_sync_on_main_thread http://localhost:6931/index.html:5161
    x http://localhost:6931/index.html:8422
    _main http://localhost:6931/index.html:9111
    callMain http://localhost:6931/index.html:9188
    doRun http://localhost:6931/index.html:9227
    run http://localhost:6931/index.html:9238
    setTimeout handler*run http://localhost:6931/index.html:9234
    runCaller http://localhost:6931/index.html:9167
    removeRunDependency http://localhost:6931/index.html:629
    receiveInstance http://localhost:6931/index.html:758
    receiveInstantiationResult http://localhost:6931/index.html:770
    promise callback*instantiateArrayBuffer http://localhost:6931/index.html:719
    instantiateAsync http://localhost:6931/index.html:727
    createWasm http://localhost:6931/index.html:789
    <anonymous> http://localhost:6931/index.html:9109
index.html:812:350

I click on it. I scroll left. I find SDL2.ctx = Module['createContext'](Module['canvas'], false, true);

now some commands I ran on my own inside browser console:

>> Module.SDL2
Object { ctx: null, ctxCanvas: canvas#canvas.emscripten }
>> Module.SDL2.ctx
null
>> Module.createContext
function createContext(canvas, useWebGL, setInModule, webGLContextAttributes)
>> Module.canvas
<canvas id="canvas" class="emscripten" oncontextmenu="event.preventDefault()" tabindex="-1" width="800" height="600" style="cursor: default;">
>> Module.createContext(Module.canvas, false, true)
null
>> Module.createContext(Module.canvas, false, false)
null
>> Module.createContext(Module.canvas, true, false)
WebGLRenderingContext { vertexAttribDivisor: vertexAttribDivisor(index, divisor), drawArraysInstanced: drawArraysInstanced(mode, first, count, primcount), drawElementsInstanced: drawElementsInstanced(mode, count, type, indices, primcount), createVertexArray: createVertexArray(), deleteVertexArray: deleteVertexArray(vao), bindVertexArray: bindVertexArray(vao), isVertexArray: isVertexArray(vao), drawBuffers: drawBuffers(n, bufs), disjointTimerQueryExt: null, multiDrawWebgl: null }
>> Module.createContext(Module.canvas, true, true)
WebGLRenderingContext { vertexAttribDivisor: vertexAttribDivisor(index, divisor), drawArraysInstanced: drawArraysInstanced(mode, first, count, primcount), drawElementsInstanced: drawElementsInstanced(mode, count, type, indices, primcount), createVertexArray: createVertexArray(), deleteVertexArray: deleteVertexArray(vao), bindVertexArray: bindVertexArray(vao), isVertexArray: isVertexArray(vao), drawBuffers: drawBuffers(n, bufs), disjointTimerQueryExt: null, multiDrawWebgl: null }

in the future I might do a binary search on Emscripten versions

Version of emscripten/emsdk:

$ emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.56-git (cf90417346b78455089e64eb909d71d091ecc055)
clang version 19.0.0git
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: C:/msys64/clang64/opt/emscripten-llvm/bin
$ emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.56 (cf90417346b78455089e64eb909d71d091ecc055)
clang version 19.0.0git (https:/github.com/llvm/llvm-project 34ba90745fa55777436a2429a51a3799c83c6d4c)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /home/dead-boy/emsdk/upstream/bin

Full link command and output with -v appended:

$ EMCC_DEBUG=1 emcc -Os -sASYNCIFY -sSINGLE_FILE -sUSE_SDL=2 random.c -o random.html -v &> clang64-emcc.txt

$ EMCC_DEBUG=1 emcc -Os -sASYNCIFY -sSINGLE_FILE -sUSE_SDL=2 random.c -o random.html -v &> wsl2.txt

$ cat random.c
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

#include <SDL.h>

#define TRY(IT) \
if ((IT)) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "%s\n", SDL_GetError()); \
            exit(EXIT_FAILURE); } else (void)0

static inline bool window_resize_maybe(SDL_Event event, int *width, int *height)
{
    if (event.type != SDL_WINDOWEVENT) return false;
    if (SDL_WINDOWEVENT_RESIZED      != event.window.event &&
        SDL_WINDOWEVENT_SIZE_CHANGED != event.window.event) return false;

    *width  = event.window.data1;
    *height = event.window.data2;

    return true;
}

static int window_width  = 800;
static int window_height = 600;

static void set_pixel(void *data, int x, int y, uint8_t r, uint8_t g, uint8_t b)
{
    if (x >= window_width || y >= window_height) return;
    SDL_Surface *surface = data;
    *(uint32_t *)(((unsigned char *)surface->pixels) + x * surface->format->BytesPerPixel + y * surface->pitch) = SDL_MapRGB(surface->format, r, g, b);
}

int main(int argc, char *argv[])
{
    (void)argc;
    (void)argv;

    srand(time(NULL));

    atexit(SDL_Quit);

    TRY(SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_EVENTS));

    SDL_Window *window = NULL;

    TRY(!(window = SDL_CreateWindow(
        "Toy Raytracing",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        window_width, window_height,
        SDL_WINDOW_RESIZABLE
    )));
    // TODO Deal with Apple's high-DPI stuff.

    SDL_Renderer *renderer = NULL;
    TRY(!(renderer = SDL_CreateRenderer(window, -1, 0)));

    SDL_Surface *surface = NULL;
    TRY(!(surface = SDL_GetWindowSurface(window)));

    for (bool is_playing = true; is_playing; )
    {
        for (SDL_Event event; SDL_PollEvent(&event); )
        {
            if (SDL_QUIT == event.type)
                is_playing = false;
            else if (SDL_KEYDOWN == event.type && 'q' == event.key.keysym.sym)
                TRY(SDL_PushEvent(&(SDL_Event){.type = SDL_QUIT}) < 0);
	    else if (window_resize_maybe(event, &window_width, &window_height))
            {
                TRY(!(surface = SDL_GetWindowSurface(window)));
            }
        }

        TRY(SDL_LockSurface(surface));

        #define DESIRED_FRAME 1000 / (float)24
        uint64_t timeout = SDL_GetTicks64() + DESIRED_FRAME;
        while (SDL_GetTicks64() < timeout)
            set_pixel(surface, rand() % window_width, rand() % window_height, rand() % 256, rand() % 256, rand() % 256);

        SDL_UnlockSurface(surface);
        SDL_UpdateWindowSurface(window);
    }

    SDL_DestroyWindow(window);

    SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_EVENTS);

    return 0;
}

sorry for not providing minimal reproducible example, I'm tired

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions