Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pressing with 2 fingers on an Emscripten web page causes an assertion failure on some tablets #14064

Open
adam4235 opened this issue Apr 30, 2021 · 2 comments

Comments

@adam4235
Copy link

adam4235 commented Apr 30, 2021

I made an Emscripten SDL webpage. When I press with 2 fingers on the webpage when running it on my Amazon Fire tablet with Firefox web browser (version 88.1.2), there's a crash / freeze. It didn't happen on 2 other tablets I tried, an iPad and a Windows tablet.

Using Firefox Remote Debugging I discovered that it's an assertion failure in the generated .js code that Emscripten created. In __registerTouchEventCallback, there are 3 assertions which all fail:

assert(!touch.isChanged);
assert(!touch.onTarget);
assert(!touch.onTarget);

This comment was an explanation for those asserts, though I don't quite understand it:
// Verify that browser does not recycle touch objects with old stale data, but reports new ones each time.

Does this mean it's a bug in the browser? If so, is there a workaround?

I reproduced it with a simple test program with Emscripten 2.0.18, as well as 1.39.18, the version I was using the most.

I think it's related to, or the same as, this bug:
#12826

In that bug, @lpotter claimed that it doesn't happen with Emscripten 1.39.8. I downgraded to that version and it also fixed my problem.

Here is my test program:

#include <iostream>
#include <cassert>

#include <SDL.h>

#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif

using namespace std;

namespace {
    /** The main SDL window */
    SDL_Window* window = NULL;
    /** The renderer used to render to the screen */
    SDL_Renderer* renderer = NULL;
    bool blink = false;
    bool quit = false;
    unsigned int currentTime = 0;
    unsigned int startTime = 0;
}

void render() {
    SDL_Rect rect;
    rect.x = 10;
    rect.y = 10;
    rect.h = 100;
    rect.w = 100;

    currentTime = SDL_GetTicks();
    unsigned int quarterSecondsSinceStart = (currentTime - startTime) / 250;
    blink = quarterSecondsSinceStart % 2 == 1;

    if (0 != SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0)) {
        printf("Error setting clear colour");
    }
    if (0 != SDL_RenderClear(renderer)) {
        printf("Error clearing");
    }

    int r, g, b;
    r = 251; g = 211; b = 146;

    if (0 != SDL_SetRenderDrawColor(renderer, r, g, b, 0)) {
        printf("Error setting colour");
    }

    if (blink) {
        if (SDL_RenderDrawRect(renderer, &rect) != 0) {
            printf("Error in SDL_RenderDrawRect");
        }
    } else {
        if (SDL_RenderFillRect(renderer, &rect) != 0) {
            printf("Error in SDL_RenderDrawRect");
        }
    }
    SDL_RenderPresent(renderer);
}

/** Called repeatedly to redraw the screen and process input */
void mainLoopFunction()
{
    //Struct for handling events
    SDL_Event input;

    render();

    //---Event polling method---
    //It runs until the number of events to be polled gets to zero
    while (SDL_PollEvent(&input) > 0)
    {
        //If they quit the game, e.g. by closing the window
        if (input.type == SDL_QUIT) {
#ifdef __EMSCRIPTEN__
            emscripten_cancel_main_loop();
#endif
            return;
        }
    }
}

int main(int argc, char** args)
{
    if (0 != SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS)) {
        printf("Error initializing SDL: %s", SDL_GetError());
        return 1;
    }

    startTime = SDL_GetTicks();

    window = SDL_CreateWindow("Test",
            SDL_WINDOWPOS_CENTERED_DISPLAY(0), SDL_WINDOWPOS_CENTERED_DISPLAY(0),
            640, 480,
            (SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE));

    if (window == NULL) {
        printf("Error creating window");
        return 1;
    } else {
        renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC);
        if (renderer == NULL) {
            printf("Error creating renderer");
            return 2;
        } else {

#ifdef __EMSCRIPTEN__
            emscripten_set_main_loop(mainLoopFunction, -1, 1);
#else
            do {
                mainLoopFunction();
            } while (quit == false);
#endif

            if (renderer) {
                SDL_DestroyRenderer(renderer);
            }
            if (window) {
                SDL_DestroyWindow(window);
            }
            SDL_Quit();
        }
    }

    return 0;
}

@adam4235
Copy link
Author

Another note is after downgrading to 1.39.8, those assertions are no longer present in the generated code, which is why it didn't crash with that version. Also, manually removing the assertions from the generated code with the newer version of Emscripten seems to fix the problem as well, with no noticeable bad effects. Perhaps they're simply mistaken asserts?

@adam4235
Copy link
Author

adam4235 commented Mar 9, 2022

With the latest version of Emscripten (3.1.7) this problem doesn't seem to happen anymore. The 3 asserts I mentioned don't seem to be present in the generated .js file. I think this problem has been fixed, either intentionally or as a result of some other change?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant