Synopsis
I have a program that pipes video out the screen directly via KMS. This program has a double-buffering scheme that modesets two frame buffers, which were allocated via libGBM. The implicit synchronization of drmModeSetCrtc() to the blanking interval essentially acts as a form of VSync. OpenGL is used to render each video frame, and the render target frame buffer is switched via eglMakeCurrent(). The buffers are locked before being modeset.
/* Main loop */
for (;;)
{
/* First buffer swap-in */
eglMakeCurrent(egldpy, eglSur1, eglSur1, eglctx);
edraw();
eglSwapBuffers(egldpy, eglSur1);
gbmbo = gbm_surface_lock_front_buffer(gbmSur1);
if (gbmbo == NULL)
fprintf(stderr, "%s: [GBM] Failed to lock buffer 2.\n", progname);
drmModeSetCrtc(gpufd, drm_crtcid, fb1, 0, 0, &drm_connid, 1, &drm_mode);
gbm_surface_release_buffer(gbmSur1, gbmbo);
gbmbo = NULL;
/* Second buffer swap-in */
eglMakeCurrent(egldpy, eglSur2, eglSur2, eglctx);
edraw();
eglSwapBuffers(egldpy, eglSur2);
gbmbo = gbm_surface_lock_front_buffer(gbmSur2);
if (gbmbo == NULL)
fprintf(stderr, "%s: [GBM] Failed to lock buffer 1.\n", progname);
drmModeSetCrtc(gpufd, drm_crtcid, fb2, 0, 0, &drm_connid, 1, &drm_mode);
gbm_surface_release_buffer(gbmSur2, gbmbo);
gbmbo = NULL;
}
The problem
On Intel GPUs, this double buffering scheme appears to work perfectly fine. However, on NVIDIA GPUs with the NVIDIA driver, this scheme causes the video to stagger. I have one theory on why this may be the case - maybe the GPU’s state is being reset every time eglMakeCurrent() is called?
Either way, a staggering, laggy video player, doesn’t make for a good experience. Is there something fundamentally wrong with my approach, or is it an issue with the driver itself?