Skip to content

Commit

Permalink
kmsdrm: Don't create surfaces until EGL context is available.
Browse files Browse the repository at this point in the history
  • Loading branch information
vanfanel committed Sep 6, 2020
1 parent 97fad04 commit d7aebbd
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 227 deletions.
34 changes: 13 additions & 21 deletions src/video/kmsdrm/SDL_kmsdrmmouse.c
Expand Up @@ -240,7 +240,6 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
SDL_DisplayData *dispdata = NULL;
KMSDRM_FBInfo *fb;
KMSDRM_PlaneInfo info = {0};
int ret;

mouse = SDL_GetMouse();
if (!mouse) {
Expand All @@ -263,11 +262,11 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
if (mouse->cur_cursor && mouse->cur_cursor->driverdata) {
if (dispdata && dispdata->cursor_plane) {
info.plane = dispdata->cursor_plane; /* The rest of the members are zeroed. */
ret = drm_atomic_set_plane_props(&info);
//drm_atomic_commit(display->device, SDL_TRUE);
if (ret) {
SDL_SetError("Could not hide current cursor.");
return ret;
if (drm_atomic_set_plane_props(&info)) {
return SDL_SetError("Failed to set CURSOR PLANE props in KMSDRM_ShowCursor.");
}
if (drm_atomic_commit(display->device, SDL_TRUE)) {
return SDL_SetError("Failed atomic commit in KMSDRM_ShowCursor.");
}

return 0;
Expand Down Expand Up @@ -314,12 +313,12 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
info.crtc_w = curdata->w;
info.crtc_h = curdata->h;

ret = drm_atomic_set_plane_props(&info);
//drm_atomic_commit(display->device, SDL_TRUE);
if (drm_atomic_set_plane_props(&info)) {
return SDL_SetError("Failed to set CURSOR PLANE props in KMSDRM_ShowCursor.");
}

if (ret) {
SDL_SetError("KMSDRM_ShowCursor failed.");
return ret;
if (drm_atomic_commit(display->device, SDL_TRUE)) {
return SDL_SetError("Failed atomic commit in KMSDRM_ShowCursor.");
}

return 0;
Expand Down Expand Up @@ -380,16 +379,11 @@ KMSDRM_WarpMouseGlobal(int x, int y)
/* And now update the cursor graphic position on screen. */
curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata;
if (curdata->bo) {
int ret;

ret = drm_atomic_movecursor(curdata, x, y);

if (ret) {
SDL_SetError("drm_atomic_movecursor() failed.");
if (drm_atomic_movecursor(curdata, x, y)) {
return SDL_SetError("drm_atomic_movecursor() failed.");
}

return ret;

} else {
return SDL_SetError("Cursor not initialized properly.");
}
Expand Down Expand Up @@ -438,7 +432,6 @@ KMSDRM_MoveCursor(SDL_Cursor * cursor)
{
SDL_Mouse *mouse = SDL_GetMouse();
KMSDRM_CursorData *curdata;
int ret;

/* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity!
That's why we move the cursor graphic ONLY. */
Expand All @@ -449,9 +442,8 @@ KMSDRM_MoveCursor(SDL_Cursor * cursor)
cursor won't move in these situations. We could do an atomic_commit() for each
cursor movement request, but it cripples the movement to 30FPS, so a future solution
is needed. SDLPoP "QUIT?" menu is an example of this situation. */
ret = drm_atomic_movecursor(curdata, mouse->x, mouse->y);

if (ret) {
if (drm_atomic_movecursor(curdata, mouse->x, mouse->y)) {
SDL_SetError("drm_atomic_movecursor() failed.");
}
}
Expand Down
62 changes: 35 additions & 27 deletions src/video/kmsdrm/SDL_kmsdrmopengles.c
Expand Up @@ -83,22 +83,10 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
KMSDRM_PlaneInfo info = {0};
int ret;

/* Do we have a pending old surfaces destruction? */
if (dispdata->destroy_surfaces_pending == SDL_TRUE) {

/* Take note that we have not pending old surfaces destruction.
Do it ASAP, DON'T GO into SwapWindowDB() with it enabled or
we will enter recursivity! */
dispdata->destroy_surfaces_pending = SDL_FALSE;

/* Do blocking pageflip, to be sure it's atomic commit is completed
before destroying the old surfaces and buffers. */
KMSDRM_GLES_SwapWindowDB(_this, window);

KMSDRM_DestroyOldSurfaces(_this);

return 0;
}
/* Recreate the GBM / EGL surfaces if the window has been reconfigured. */
if (windata->egl_surface_dirty) {
KMSDRM_CreateSurfaces(_this, window);
}

/*************************************************************************/
/* Block for telling KMS to wait for GPU rendering of the current frame */
Expand All @@ -112,7 +100,9 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)

/* Mark, at EGL level, the buffer that we want to become the new front buffer.
However, it won't really happen until we request a pageflip at the KMS level and it completes. */
_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface);
if (! _this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface)) {
return SDL_SetError("Failed to swap EGL buffers");
}

/* It's safe to get the gpu_fence FD now, because eglSwapBuffers flushes it down the cmdstream,
so it's now in place in the cmdstream.
Expand Down Expand Up @@ -154,6 +144,15 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
return SDL_SetError("Failed to request prop changes for setting plane buffer and CRTC");
}

/* Re-connect the connector to the CRTC, and activate the CRTC again.
Just in case we come here after a DestroySurfaces() call. */
if (add_connector_property(dispdata->atomic_req, dispdata->connector , "CRTC_ID",
dispdata->crtc->crtc->crtc_id) < 0)
SDL_SetError("Failed to set CONNECTOR prop CRTC_ID to zero before buffer destruction");

if (add_crtc_property(dispdata->atomic_req, dispdata->crtc , "ACTIVE", 1) < 0)
SDL_SetError("Failed to set CRTC prop ACTIVE to zero before buffer destruction");

/* Set the IN_FENCE and OUT_FENCE props only here, since this is the only place
on which we're interested in managing who and when should access the buffers
that the display plane uses, and that's what these props are for. */
Expand Down Expand Up @@ -213,6 +212,11 @@ KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)
KMSDRM_PlaneInfo info = {0};
int ret;

/* Recreate the GBM / EGL surfaces if the window has been reconfigured. */
if (windata->egl_surface_dirty) {
KMSDRM_CreateSurfaces(_this, window);
}

/****************************************************************************************************/
/* In double-buffer mode, atomic commit will always be synchronous/blocking (ie: won't return until */
/* the requested changes are really done). */
Expand All @@ -222,7 +226,10 @@ KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)

/* Mark, at EGL level, the buffer that we want to become the new front buffer.
However, it won't really happen until we request a pageflip at the KMS level and it completes. */
_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface);
if (! _this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface)) {
SDL_EGL_SetError("Failed to swap EGL buffers", "eglSwapBuffers");
printf("SwapWindow() failed: %s\n", SDL_GetError());
}

/* Lock the buffer that is marked by eglSwapBuffers() to become the next front buffer (so it can not
be chosen by EGL as back buffer to draw on), and get a handle to it to request the pageflip on it. */
Expand All @@ -247,10 +254,19 @@ KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)
info.crtc_x = windata->output_x;

ret = drm_atomic_set_plane_props(&info);
if (ret) {
if (ret) {
return SDL_SetError("Failed to request prop changes for setting plane buffer and CRTC");
}

/* Re-connect the connector to the CRTC, and activate the CRTC again.
Just in case we come here after a DestroySurfaces() call. */
if (add_connector_property(dispdata->atomic_req, dispdata->connector , "CRTC_ID",
dispdata->crtc->crtc->crtc_id) < 0)
SDL_SetError("Failed to set CONNECTOR prop CRTC_ID to zero before buffer destruction");

if (add_crtc_property(dispdata->atomic_req, dispdata->crtc , "ACTIVE", 1) < 0)
SDL_SetError("Failed to set CRTC prop ACTIVE to zero before buffer destruction");

/* Issue the one and only atomic commit where all changes will be requested!.
Blocking for double buffering: won't return until completed. */
ret = drm_atomic_commit(_this, SDL_TRUE);
Expand All @@ -267,14 +283,6 @@ KMSDRM_GLES_SwapWindowDB(_THIS, SDL_Window * window)
/* Take note of current front buffer, so we can free it next time we come here. */
windata->bo = windata->next_bo;

/* Do we have a pending old surfaces destruction? */
if (dispdata->destroy_surfaces_pending == SDL_TRUE) {
/* We have just done a blocking pageflip to the new buffers already,
so just do what you are here for... */
KMSDRM_DestroyOldSurfaces(_this);
dispdata->destroy_surfaces_pending = SDL_FALSE;
}

return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion src/video/kmsdrm/SDL_kmsdrmopengles.h
Expand Up @@ -32,7 +32,7 @@
/* OpenGLES functions */
#define KMSDRM_GLES_GetAttribute SDL_EGL_GetAttribute
#define KMSDRM_GLES_GetProcAddress SDL_EGL_GetProcAddress
//#define KMSDRM_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
#define KMSDRM_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
#define KMSDRM_GLES_DeleteContext SDL_EGL_DeleteContext
#define KMSDRM_GLES_GetSwapInterval SDL_EGL_GetSwapInterval

Expand Down

0 comments on commit d7aebbd

Please sign in to comment.