floooh / sokol

minimal cross-platform standalone C headers
https://floooh.github.io/sokol-html5
zlib License
6.82k stars 475 forks source link

Allow developer to flush manually #840

Closed ivan-ushakov closed 1 year ago

ivan-ushakov commented 1 year ago

Currently in macOS you flush OpenGL context after each onFrame call:

- (void)drawRect:(NSRect)rect {
    _SOKOL_UNUSED(rect);
    _sapp_timing_measure(&_sapp.timing);
    /* Catch any last-moment input events */
    _sapp_macos_poll_input_events();
    @autoreleasepool {
        _sapp_macos_frame();
    }
    #if !defined(SOKOL_METAL)
    [[_sapp.macos.view openGLContext] flushBuffer];
    #endif
}

In some cases this leads to blinking black screen if we don't have any draw commands during onFrame. Would be great to have something like:

SOKOL_API_IMPL void sapp_gl_flush(void) {
    #if defined(_SAPP_MACOS) && !defined(SOKOL_METAL)
    [[_sapp.macos.view openGLContext] flushBuffer];
    #endif
}
floooh commented 1 year ago

Unfortunately this would be a hack that would only work by accident, and most likely only on macOS.

sokol_app.h basically expects that something is rendered in each frame (and if it's just an empty render pass which clears the screen). Failing to do this may result in all sorts of breakage: from black screen, to corrupted screen, to flickering because the last two rendered frames are alternated.

A proper solution is sketched out in this ticket: https://github.com/floooh/sokol/issues/301

(basically having a paused mode where sokol_app.h "somehow" preserves the last rendered frame, it's not clear yet whether that can be done on all platforms).

I'm closing this ticket. Until a proper solution is implement a workaround is to do your regular rendering into an offscreen render target, which is then rendered to the default framebuffer. If your app needs to "freeze", skip the expensive offscreen rendering, but keep the default render pass active which renders the last content of the offscreen render target to the screen.