SDL  2.0
SDL_kmsdrmopengles.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2019 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) {
40  return SDL_EGL_LoadLibrary(_this, path, ((SDL_VideoData *)_this->driverdata)->gbm, EGL_PLATFORM_GBM_MESA);
41 }
42 
43 SDL_EGL_CreateContext_impl(KMSDRM)
44 
46 KMSDRM_GLES_SetupCrtc(_THIS, SDL_Window * window) {
47  SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
50  KMSDRM_FBInfo *fb_info;
51 
52  if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
53  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed on CRTC setup");
54  return SDL_FALSE;
55  }
56 
57  wdata->crtc_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
58  if (wdata->crtc_bo == NULL) {
59  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer on CRTC setup");
60  return SDL_FALSE;
61  }
62 
63  fb_info = KMSDRM_FBFromBO(_this, wdata->crtc_bo);
64  if (fb_info == NULL) {
65  return SDL_FALSE;
66  }
67 
68  if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
69  0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode) != 0) {
70  SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC to a GBM buffer");
71  return SDL_FALSE;
72 
73  }
74 
75  wdata->crtc_ready = SDL_TRUE;
76  return SDL_TRUE;
77 }
78 
79 int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
80  if (!_this->egl_data) {
81  return SDL_SetError("EGL not initialized");
82  }
83 
84  if (interval == 0 || interval == 1) {
85  _this->egl_data->egl_swapinterval = interval;
86  } else {
87  return SDL_SetError("Only swap intervals of 0 or 1 are supported");
88  }
89 
90  return 0;
91 }
92 
93 int
95  SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
98  KMSDRM_FBInfo *fb_info;
99  int ret;
100 
101  /* Do we still need to wait for a flip? */
102  int timeout = 0;
103  if (_this->egl_data->egl_swapinterval == 1) {
104  timeout = -1;
105  }
106  if (!KMSDRM_WaitPageFlip(_this, wdata, timeout)) {
107  return 0;
108  }
109 
110  /* Release previously displayed buffer (which is now the backbuffer) and lock a new one */
111  if (wdata->next_bo != NULL) {
112  KMSDRM_gbm_surface_release_buffer(wdata->gs, wdata->current_bo);
113  /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)wdata->next_bo); */
114 
115  wdata->current_bo = wdata->next_bo;
116  wdata->next_bo = NULL;
117  }
118 
119  if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
120  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
121  return 0;
122  }
123 
124  if (wdata->current_bo == NULL) {
125  wdata->current_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
126  if (wdata->current_bo == NULL) {
127  return 0;
128  }
129  }
130 
131  wdata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
132  if (wdata->next_bo == NULL) {
133  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
134  return 0;
135  /* } else {
136  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)wdata->next_bo); */
137  }
138 
139  fb_info = KMSDRM_FBFromBO(_this, wdata->next_bo);
140  if (fb_info == NULL) {
141  return 0;
142  }
143  if (_this->egl_data->egl_swapinterval == 0) {
144  /* Swap buffers instantly, possible tearing */
145  /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)",
146  vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, vdata->saved_conn_id,
147  displaydata->cur_mode.hdisplay, displaydata->cur_mode.vdisplay, displaydata->cur_mode.vrefresh); */
148  ret = KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
149  0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode);
150  if(ret != 0) {
151  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not pageflip with drmModeSetCrtc: %d", ret);
152  }
153  } else {
154  /* Queue page flip at vsync */
155 
156  /* Have we already setup the CRTC to one of the GBM buffers? Do so if we have not,
157  or FlipPage won't work in some cases. */
158  if (!wdata->crtc_ready) {
159  if(!KMSDRM_GLES_SetupCrtc(_this, window)) {
160  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set up CRTC for doing vsync-ed pageflips");
161  return 0;
162  }
163  }
164 
165  /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)",
166  vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
167  ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
168  DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip);
169  if (ret == 0) {
170  wdata->waiting_for_flip = SDL_TRUE;
171  } else {
172  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
173  }
174 
175  /* Wait immediately for vsync (as if we only had two buffers), for low input-lag scenarios.
176  Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>" to enable this. */
177  if (wdata->double_buffer) {
178  KMSDRM_WaitPageFlip(_this, wdata, -1);
179  }
180  }
181 
182  return 0;
183 }
184 
185 SDL_EGL_MakeCurrent_impl(KMSDRM)
186 
187 #endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */
188 
189 /* vi: set ts=4 sw=4 expandtab: */
SDL_WindowData::current_bo
struct gbm_bo * current_bo
Definition: SDL_kmsdrmvideo.h:63
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:381
SDL_kmsdrmvideo.h
NULL
#define NULL
Definition: begin_code.h:167
KMSDRM_FBInfo
Definition: SDL_kmsdrmvideo.h:74
timeout
GLbitfield GLuint64 timeout
Definition: SDL_opengl_glext.h:1483
SDL_WindowData::next_bo
struct gbm_bo * next_bo
Definition: SDL_kmsdrmvideo.h:64
SDL_log.h
SDL_WindowData
Definition: SDL_androidwindow.h:38
SDL_GetDisplayForWindow
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1089
KMSDRM_GLES_LoadLibrary
int KMSDRM_GLES_LoadLibrary(_THIS, const char *path)
KMSDRM_GLES_SetSwapInterval
int KMSDRM_GLES_SetSwapInterval(_THIS, int interval)
path
GLsizei const GLchar *const * path
Definition: SDL_opengl_glext.h:3730
SDL_LogError
#define SDL_LogError
Definition: SDL_dynapi_overrides.h:36
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_WindowData::gs
struct gbm_surface * gs
Definition: SDL_kmsdrmvideo.h:62
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_WindowData::crtc_ready
SDL_bool crtc_ready
Definition: SDL_kmsdrmvideo.h:67
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
SDL_LOG_CATEGORY_VIDEO
@ SDL_LOG_CATEGORY_VIDEO
Definition: SDL_log.h:71
SDL_kmsdrmopengles.h
SDL_WindowData::crtc_bo
struct gbm_bo * crtc_bo
Definition: SDL_kmsdrmvideo.h:65
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_DisplayData::cur_mode
drmModeModeInfo cur_mode
Definition: SDL_kmsdrmvideo.h:56
SDL_VideoDisplay::driverdata
void * driverdata
Definition: SDL_sysvideo.h:139
KMSDRM_WaitPageFlip
SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout)
SDL_DisplayData
Definition: SDL_cocoamodes.h:26
SDL_VideoData::drm_fd
int drm_fd
Definition: SDL_kmsdrmvideo.h:42
SDL_WindowData::double_buffer
SDL_bool double_buffer
Definition: SDL_kmsdrmvideo.h:68
SDL_WindowData::waiting_for_flip
SDL_bool waiting_for_flip
Definition: SDL_kmsdrmvideo.h:66
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
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:55
SDL_LogWarn
#define SDL_LogWarn
Definition: SDL_dynapi_overrides.h:35
SDL_WindowData::egl_surface
EGLSurface egl_surface
Definition: SDL_androidwindow.h:40
SDL_VideoData::saved_conn_id
uint32_t saved_conn_id
Definition: SDL_kmsdrmvideo.h:47
SDL_VideoData
Definition: SDL_androidvideo.h:36
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
KMSDRM_FBInfo::fb_id
uint32_t fb_id
Definition: SDL_kmsdrmvideo.h:77