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

"Cannot set timing mode for main loop" & "You should use 0 for the frame rate in emscripten_set_main_loop" #7100

Closed
fgoujeon opened this issue Sep 7, 2018 · 10 comments
Labels

Comments

@fgoujeon
Copy link

fgoujeon commented Sep 7, 2018

With the following program…:

#include <SDL2/SDL.h>
#include <emscripten.h>

void iterate()
{
}

int main(int, char**)
{
    auto pwindow = SDL_CreateWindow
    (
        "Test",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        640,
        480,
        SDL_WINDOW_RESIZABLE
    );

    auto prenderer = SDL_CreateRenderer
    (
        pwindow,
        -1,
        0
    );

    emscripten_set_main_loop(iterate, 0, 1);

    return 0;
}

… I get the following error in the web console: emscripten_set_main_loop_timing: Cannot set timing mode for main loop since a main loop does not exist! Call emscripten_set_main_loop first to set one up.

Since emscripten_set_main_loop_timing seems to be called by SDL_CreateRenderer, I try to fix my program like so:

#include <SDL2/SDL.h>
#include <emscripten.h>

void iterate()
{
    SDL_Window* pwindow;
    SDL_Renderer* prenderer;
    static auto first_call = true;

    if(first_call)
    {
        pwindow = SDL_CreateWindow
        (
            "Test",
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            640,
            480,
            SDL_WINDOW_RESIZABLE
        );

        prenderer = SDL_CreateRenderer
        (
            pwindow,
            -1,
            0
        );

        first_call = false;
    }
}

int main(int, char**)
{
    emscripten_set_main_loop(iterate, 0, 1);

    return 0;
}

But now I get the following warning in the web console: Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!

It seems like there's no way to get neither of those errors.

@kripken
Copy link
Member

kripken commented Sep 11, 2018

This does seem odd, I'm not sure why SDL_CreateRenderer affects the main loop. And I confirm I see those warnings on the two cases in the test suite that use those two functions (tests/sdl2_gl_frames_swap.c, tests/sdl_togglefullscreen.c).

cc @Daft-Freak

@Daft-Freak
Copy link
Collaborator

For the second message, try creating the renderer with the SDL_RENDERER_PRESENTVSYNC flag. I think if you don't pass that the GLES renderer does eglSwapInterval(0). The first message is probably caused by the fact that it calls eglSwapInterval as well.

@rschulman
Copy link

I'm having this same problem in porting a game to wasm. The code calls SDL_CreateRenderer long before the main loop is entered while setting up the UI for the first time. I get an error that it can't set timing because a main loop doesn't exist. I tried @Daft-Freak's suggestion to add the PRESENTVSYNC flag, but it doesn't seem to have changed anything. Any other ideas?

@julitopower
Copy link

I am experiencing the same error "Cannot set timing, ..." with the following code

#include <iostream>

#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

#include <emscripten.h>

void loop_handler(void*) {
  
}

int main(int argc, char** argv) {
  
  SDL_Init(SDL_INIT_VIDEO);
  TTF_Init();
  
  SDL_Window* win = SDL_CreateWindow("WebAssembly test", 0, 0, 800, 600, 0);
  SDL_Renderer* renderer = SDL_CreateRenderer(win, 0, 0);

  
  TTF_Font* font = TTF_OpenFont("assets/DejaVuSansMono.ttf", 100);
  SDL_Color white = {255, 255, 255};
  SDL_Surface* sf = TTF_RenderText_Solid(font, "WebAssembly rocks!", white);
  SDL_Texture* tex = SDL_CreateTextureFromSurface(renderer, sf);

  emscripten_set_main_loop_arg(loop_handler, nullptr, -1, 1);
  //  SDL_RenderCopy(renderer, tex, nullptr, nullptr);
  //  SDL_RenderPresent(renderer);  


  // std::cout << std::endl << "Hello World" << std::endl;

  // SDL_DestroyTexture(tex);
  // SDL_FreeSurface(sf);
  // SDL_DestroyRenderer(renderer);
  // SDL_DestroyWindow(win);

  // TTF_CloseFont(font);
  // TTF_Quit();
  // SDL_Quit();

  return 0;
}

@Daft-Freak
Copy link
Collaborator

You can just ignore the error, it's only there when ASSERTIONS is enabled and the main loop still gets created. To fix this we either need to allow calling emscripten_set_main_loop_timing before creating the main loop, or change eglSwapInterval to not use it.

@royalstream
Copy link

royalstream commented Jan 9, 2020

The warning goes away if I do this, but I wonder if this could have other consequences:

#include <SDL2/SDL.h>
#include <emscripten.h>

void iterate()
{
    // Here I have some code animating a sprite
}

int main(int, char**)
{
    SDL_Init( SDL_INIT_VIDEO ); // I have this call, I guess it makes no difference

    emscripten_set_main_loop(iterate, 0, 1); // moved before creating window and renderer

    auto pwindow = SDL_CreateWindow
    (
        "Test",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        640,
        480,
        SDL_WINDOW_RESIZABLE
    );

    auto prenderer = SDL_CreateRenderer
    (
        pwindow,
        -1,
        0
    );
    
   return 0;
}

@Daft-Freak
Copy link
Collaborator

That shouldn't work as emscripten_set_main_loop doesn't return, so your window/renderer won't be getting created. Also, calling SDL_CreateRenderer after setting the main loop overrides the main loop timing based on the SDL_RENDERER_PRESENTVSYNC flag. (EM_TIMING_RAF if set, EM_TIMING_SETTIMEOUT otherwise.)

Where the warning comes from:
SDL_CreateRenderer(..., 0) ->
GLES2_CreateRenderer(..., 0) ->
SDL_GL_SetSwapInterval(0) ->
SDL_EGL_SetSwapInterval(..., 0) ->
eglSwapInterval(... 0) ->
emscripten_set_main_loop_timing(EM_TIMING_SETTIMEOUT, 0) ->
"Looks like you are rendering without using requestAnimationFrame for the main loop..."

@royalstream
Copy link

royalstream commented Jan 16, 2020

Never mind then. I was assuming emscripten_set_main_loop only stored a pointer to the iterate function and returned right away.

@alienzhou
Copy link

I have the same errors. However, in my practice, "Cannot set timing mode for main loop" error message wont break the application. It is more like a warning.

@stale
Copy link

stale bot commented Feb 2, 2021

This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 30 days. Feel free to re-open at any time if this issue is still relevant.

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

No branches or pull requests

7 participants