kmsdrm: Choose how to swap buffers based on EGL extension availability.

This commit is contained in:
Ryan C. Gordon 2020-09-10 15:07:23 -04:00
parent c7e761f872
commit 3c6004feb7
4 changed files with 36 additions and 40 deletions

View file

@ -27,6 +27,7 @@
#include "SDL_kmsdrmvideo.h"
#include "SDL_kmsdrmopengles.h"
#include "SDL_kmsdrmdyn.h"
#include "SDL_hints.h"
#ifndef EGL_PLATFORM_GBM_MESA
#define EGL_PLATFORM_GBM_MESA 0x31D7
@ -99,30 +100,18 @@ static EGLSyncKHR create_fence(int fd, _THIS)
return fence;
}
int
KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
static int
KMSDRM_GLES_SwapWindowFenced(_THIS, SDL_Window * window)
{
SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
KMSDRM_FBInfo *fb;
KMSDRM_PlaneInfo info = {0};
/* Get the EGL context, now that SDL_CreateRenderer() has already been called,
and call eglMakeCurrent() on it and the EGL surface. */
#if SDL_VIDEO_OPENGL_EGL
if (windata->egl_context_pending) {
EGLContext egl_context;
egl_context = (EGLContext)SDL_GL_GetCurrentContext();
SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
windata->egl_context_pending = SDL_FALSE;
}
#endif
/*************************************************************************/
/* Block for telling KMS to wait for GPU rendering of the current frame */
/* before applying the KMS changes requested in the atomic ioctl. */
/*************************************************************************/
/* Create the fence that will be inserted in the cmdstream exactly at the end
of the gl commands that form a frame. KMS will have to wait on it before doing a pageflip. */
dispdata->gpu_fence = create_fence(EGL_NO_NATIVE_FENCE_FD_ANDROID, _this);
@ -222,25 +211,14 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
return 0;
}
int
KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)
static int
KMSDRM_GLES_SwapWindowDoubleBuffered(_THIS, SDL_Window * window)
{
SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
KMSDRM_FBInfo *fb;
KMSDRM_PlaneInfo info = {0};
/* Get the EGL context, now that SDL_CreateRenderer() has already been called,
and call eglMakeCurrent() on it and the EGL surface. */
#if SDL_VIDEO_OPENGL_EGL
if (windata->egl_context_pending) {
EGLContext egl_context;
egl_context = (EGLContext)SDL_GL_GetCurrentContext();
SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
windata->egl_context_pending = SDL_FALSE;
}
#endif
/****************************************************************************************************/
/* In double-buffer mode, atomic commit will always be synchronous/blocking (ie: won't return until */
/* the requested changes are really done). */
@ -306,6 +284,34 @@ KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)
return 0;
}
int
KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
/* Get the EGL context, now that SDL_CreateRenderer() has already been called,
and call eglMakeCurrent() on it and the EGL surface. */
#if SDL_VIDEO_OPENGL_EGL
if (windata->egl_context_pending) {
EGLContext egl_context = (EGLContext)SDL_GL_GetCurrentContext();
SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
windata->egl_context_pending = SDL_FALSE;
}
#endif
if (windata->swap_window == NULL) {
/* We want the fenced version by default, but it needs extensions. */
if ( (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) ||
(!SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_ANDROID_native_fence_sync")) ) {
windata->swap_window = KMSDRM_GLES_SwapWindowDoubleBuffered;
} else {
windata->swap_window = KMSDRM_GLES_SwapWindowFenced;
}
}
return windata->swap_window(_this, window);
}
/***************************************/
/* End of Atomic functions block */

View file

@ -41,7 +41,6 @@ extern int KMSDRM_GLES_SetSwapInterval(_THIS, int interval);
extern int KMSDRM_GLES_LoadLibrary(_THIS, const char *path);
extern SDL_GLContext KMSDRM_GLES_CreateContext(_THIS, SDL_Window * window);
extern int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window);
extern int KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window);
extern int KMSDRM_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
#endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */

View file

@ -27,7 +27,6 @@
/* SDL internals */
#include "../SDL_sysvideo.h"
#include "SDL_syswm.h"
#include "SDL_hints.h"
#include "../../events/SDL_events_c.h"
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_keyboard_c.h"
@ -50,7 +49,6 @@
#define KMSDRM_DRI_PATH "/dev/dri/"
#define AMDGPU_COMPAT 1
#define RPI4_COMPAT 0
static int
check_modesetting(int devindex)
@ -792,16 +790,7 @@ KMSDRM_CreateDevice(int devindex)
device->GL_MakeCurrent = KMSDRM_GLES_MakeCurrent;
device->GL_SetSwapInterval = KMSDRM_GLES_SetSwapInterval;
device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval;
#if RPI4_COMPAT
device->GL_SwapWindow = KMSDRM_GLES_SwapWindowDB;
#else
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE))
device->GL_SwapWindow = KMSDRM_GLES_SwapWindowDB;
else
device->GL_SwapWindow = KMSDRM_GLES_SwapWindow;
#endif
device->GL_SwapWindow = KMSDRM_GLES_SwapWindow;
device->GL_DeleteContext = KMSDRM_GLES_DeleteContext;
#endif
device->PumpEvents = KMSDRM_PumpEvents;

View file

@ -171,6 +171,8 @@ typedef struct SDL_WindowData
the EGL context is available, but we need the EGL surface sooner. */
SDL_bool egl_context_pending;
/* This dictates what approach we'll use for SwapBuffers. */
int (*swap_window)(_THIS, SDL_Window * window);
} SDL_WindowData;
typedef struct SDL_DisplayModeData