SDL  2.0
SDL_kmsdrmopengles.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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->next_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
58  if (wdata->next_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->next_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_bool double_buffer
drmModeModeInfo cur_mode
SDL_bool waiting_for_flip
struct gbm_bo * current_bo
int KMSDRM_GLES_SetSwapInterval(_THIS, int interval)
int KMSDRM_GLES_LoadLibrary(_THIS, const char *path)
#define SDL_LogError
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
#define _THIS
SDL_bool crtc_ready
SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout)
#define NULL
Definition: begin_code.h:164
SDL_bool
Definition: SDL_stdinc.h:139
#define SDL_SetError
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1073
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
struct gbm_surface * gs
The type used to identify a window.
Definition: SDL_sysvideo.h:73
GLbitfield GLuint64 timeout
struct gbm_bo * next_bo
#define EGL_PLATFORM_GBM_MESA
Definition: eglext.h:956
GLsizei const GLchar *const * path
KMSDRM_FBInfo * KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
void * driverdata
Definition: SDL_sysvideo.h:111
#define SDL_LogWarn
int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window *window)
uint32_t saved_conn_id
EGLSurface egl_surface