SDL  2.0
SDL_kmsdrmopengles.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 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 
45 int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
46  if (!_this->egl_data) {
47  return SDL_SetError("EGL not initialized");
48  }
49 
50  if (interval == 0 || interval == 1) {
51  _this->egl_data->egl_swapinterval = interval;
52  } else {
53  return SDL_SetError("Only swap intervals of 0 or 1 are supported");
54  }
55 
56  return 0;
57 }
58 
59 int
61  SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
64  KMSDRM_FBInfo *fb_info;
65  int ret;
66 
67  /* Do we still need to wait for a flip? */
68  int timeout = 0;
69  if (_this->egl_data->egl_swapinterval == 1) {
70  timeout = -1;
71  }
72  if (!KMSDRM_WaitPageFlip(_this, wdata, timeout)) {
73  return 0;
74  }
75 
76  /* Release previously displayed buffer (which is now the backbuffer) and lock a new one */
77  if (wdata->next_bo != NULL) {
78  KMSDRM_gbm_surface_release_buffer(wdata->gs, wdata->current_bo);
79  /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Released GBM surface %p", (void *)wdata->next_bo); */
80 
81  wdata->current_bo = wdata->next_bo;
82  wdata->next_bo = NULL;
83  }
84 
85  if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
86  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
87  return 0;
88  }
89 
90  if (wdata->current_bo == NULL) {
91  wdata->current_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
92  if (wdata->current_bo == NULL) {
93  return 0;
94  }
95  }
96 
97  wdata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(wdata->gs);
98  if (wdata->next_bo == NULL) {
99  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
100  return 0;
101  /* } else {
102  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Locked GBM surface %p", (void *)wdata->next_bo); */
103  }
104 
105  fb_info = KMSDRM_FBFromBO(_this, wdata->next_bo);
106  if (fb_info == NULL) {
107  return 0;
108  }
109  if (_this->egl_data->egl_swapinterval == 0) {
110  /* Swap buffers instantly, possible tearing */
111  /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModeSetCrtc(%d, %u, %u, 0, 0, &%u, 1, &%ux%u@%u)",
112  vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id, vdata->saved_conn_id,
113  displaydata->cur_mode.hdisplay, displaydata->cur_mode.vdisplay, displaydata->cur_mode.vrefresh); */
114  ret = KMSDRM_drmModeSetCrtc(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
115  0, 0, &vdata->saved_conn_id, 1, &displaydata->cur_mode);
116  if(ret != 0) {
117  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not pageflip with drmModeSetCrtc: %d", ret);
118  }
119  } else {
120  /* Queue page flip at vsync */
121  /* SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "drmModePageFlip(%d, %u, %u, DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip)",
122  vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id); */
123  ret = KMSDRM_drmModePageFlip(vdata->drm_fd, displaydata->crtc_id, fb_info->fb_id,
124  DRM_MODE_PAGE_FLIP_EVENT, &wdata->waiting_for_flip);
125  if (ret == 0) {
126  wdata->waiting_for_flip = SDL_TRUE;
127  } else {
128  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
129  }
130  }
131 
132  return 0;
133 }
134 
135 SDL_EGL_MakeCurrent_impl(KMSDRM)
136 
137 #endif /* SDL_VIDEO_DRIVER_KMSDRM && SDL_VIDEO_OPENGL_EGL */
138 
139 /* vi: set ts=4 sw=4 expandtab: */
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 KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout)
#define NULL
Definition: begin_code.h:164
#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
int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window *window)
uint32_t saved_conn_id
EGLSurface egl_surface