SDL  2.0
SDL_kmsdrmopengles.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 
22 #include "../../SDL_internal.h"
23 
24 #if SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL
25 
26 #include "SDL_log.h"
27 
28 #include "SDL_kmsdrmvideo.h"
29 #include "SDL_kmsdrmopengles.h"
30 #include "SDL_kmsdrmdyn.h"
31 
32 #ifndef EGL_PLATFORM_GBM_MESA
33 #define EGL_PLATFORM_GBM_MESA 0x31D7
34 #endif
35 
36 /* EGL implementation of SDL OpenGL support */
37 
38 int
39 KMSDRM_GLES_LoadLibrary(_THIS, const char *path) {
41  return SDL_EGL_LoadLibrary(_this, path, display, EGL_PLATFORM_GBM_MESA);
42 }
43 
44 SDL_EGL_CreateContext_impl(KMSDRM)
45 
46 int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
47  if (!_this->egl_data) {
48  return SDL_SetError("EGL not initialized");
49  }
50 
51  if (interval == 0 || interval == 1) {
52  _this->egl_data->egl_swapinterval = interval;
53  } else {
54  return SDL_SetError("Only swap intervals of 0 or 1 are supported");
55  }
56 
57  return 0;
58 }
59 
60 int
62  SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
65  KMSDRM_FBInfo *fb_info;
66  int ret, timeout;
67 
68  /* Recreate the GBM / EGL surfaces if the display mode has changed */
69  if (windata->egl_surface_dirty) {
71  }
72 
73  /* Wait for confirmation that the next front buffer has been flipped, at which
74  point the previous front buffer can be released */
75  timeout = 0;
76  if (_this->egl_data->egl_swapinterval == 1) {
77  timeout = -1;
78  }
79  if (!KMSDRM_WaitPageFlip(_this, windata, timeout)) {
80  return 0;
81  }
82 
83  /* Release the previous front buffer */
84  if (windata->curr_bo) {
85  KMSDRM_gbm_surface_release_buffer(windata->gs, windata->curr_bo);
86  /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)windata->curr_bo); */
87  windata->curr_bo = NULL;
88  }
89 
90  windata->curr_bo = windata->next_bo;
91 
92  /* Make the current back buffer the next front buffer */
93  if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface))) {
94  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
95  return 0;
96  }
97 
98  /* Lock the next front buffer so it can't be allocated as a back buffer */
99  windata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(windata->gs);
100  if (!windata->next_bo) {
101  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
102  return 0;
103  /* } else {
104  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)windata->next_bo); */
105  }
106 
107  fb_info = KMSDRM_FBFromBO(_this, windata->next_bo);
108  if (!fb_info) {
109  return 0;
110  }
111 
112  if (!windata->curr_bo) {
113  /* On the first swap, immediately present the new front buffer. Before
114  drmModePageFlip can be used the CRTC has to be configured to use
115  the current connector and mode with drmModeSetCrtc */
116  ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id, 0,
117  0, &dispdata->conn->connector_id, 1, &dispdata->mode);
118 
119  if (ret) {
120  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not configure CRTC");
121  }
122  } else {
123  /* On subsequent swaps, queue the new front buffer to be flipped during
124  the next vertical blank */
125  ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc_id, fb_info->fb_id,
126  DRM_MODE_PAGE_FLIP_EVENT, &windata->waiting_for_flip);
127  /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &windata->waiting_for_flip)",
128  viddata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
129 
130  if (_this->egl_data->egl_swapinterval == 1) {
131  if (ret == 0) {
132  windata->waiting_for_flip = SDL_TRUE;
133  } else {
134  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
135  }
136  }
137 
138  /* Wait immediately for vsync (as if we only had two buffers), for low input-lag scenarios.
139  Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>" to enable this. */
140  if (_this->egl_data->egl_swapinterval == 1 && windata->double_buffer) {
141  KMSDRM_WaitPageFlip(_this, windata, -1);
142  }
143  }
144 
145  return 0;
146 }
147 
148 SDL_EGL_MakeCurrent_impl(KMSDRM)
149 
150 #endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */
151 
152 /* vi: set ts=4 sw=4 expandtab: */
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:389
SDL_kmsdrmvideo.h
NULL
#define NULL
Definition: begin_code.h:167
KMSDRM_FBInfo
Definition: SDL_kmsdrmvideo.h:81
timeout
GLbitfield GLuint64 timeout
Definition: SDL_opengl_glext.h:1486
SDL_WindowData::next_bo
struct gbm_bo * next_bo
Definition: SDL_kmsdrmvideo.h:70
SDL_log.h
SDL_WindowData
Definition: SDL_androidwindow.h:39
SDL_GetDisplayForWindow
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1110
SDL_WindowData::curr_bo
struct gbm_bo * curr_bo
Definition: SDL_kmsdrmvideo.h:69
KMSDRM_GLES_LoadLibrary
int KMSDRM_GLES_LoadLibrary(_THIS, const char *path)
KMSDRM_GLES_SetSwapInterval
int KMSDRM_GLES_SetSwapInterval(_THIS, int interval)
gbm
int uint32_t uint32_t uint32_t uint32_t uint32_t int drmModeModeInfoPtr mode int uint32_t uint32_t uint32_t uint32_t int32_t int32_t hot_y struct gbm_device * gbm
Definition: SDL_kmsdrmsym.h:68
SDL_DisplayData::mode
drmModeModeInfo mode
Definition: SDL_kmsdrmvideo.h:60
path
GLsizei const GLchar *const * path
Definition: SDL_opengl_glext.h:3733
KMSDRM_CreateSurfaces
int KMSDRM_CreateSurfaces(_THIS, SDL_Window *window)
SDL_LogError
#define SDL_LogError
Definition: SDL_dynapi_overrides.h:36
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:75
SDL_DisplayData::conn
drmModeConnector * conn
Definition: SDL_kmsdrmvideo.h:59
SDL_WindowData::gs
struct gbm_surface * gs
Definition: SDL_kmsdrmvideo.h:68
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
NativeDisplayType
EGLNativeDisplayType NativeDisplayType
Definition: eglplatform.h:110
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
KMSDRM_WaitPageFlip
SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata, int timeout)
SDL_kmsdrmopengles.h
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_VideoDisplay::driverdata
void * driverdata
Definition: SDL_sysvideo.h:140
SDL_DisplayData
Definition: SDL_cocoamodes.h:27
SDL_VideoData::drm_fd
int drm_fd
Definition: SDL_kmsdrmvideo.h:41
SDL_WindowData::double_buffer
SDL_bool double_buffer
Definition: SDL_kmsdrmvideo.h:73
SDL_WindowData::waiting_for_flip
SDL_bool waiting_for_flip
Definition: SDL_kmsdrmvideo.h:72
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_kmsdrmdyn.h
KMSDRM_FBFromBO
KMSDRM_FBInfo * KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
EGL_PLATFORM_GBM_MESA
#define EGL_PLATFORM_GBM_MESA
Definition: eglext.h:956
KMSDRM_GLES_SwapWindow
int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window *window)
SDL_DisplayData::crtc_id
uint32_t crtc_id
Definition: SDL_kmsdrmvideo.h:58
SDL_WindowData::egl_surface
EGLSurface egl_surface
Definition: SDL_androidwindow.h:40
SDL_VideoData
Definition: SDL_androidvideo.h:37
SDL_LOG_CATEGORY_VIDEO
@ SDL_LOG_CATEGORY_VIDEO
Definition: SDL_log.h:71
KMSDRM_FBInfo::fb_id
uint32_t fb_id
Definition: SDL_kmsdrmvideo.h:83