SDL  2.0
SDL_kmsdrmvideo.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
25 
26 /* SDL internals */
27 #include "../SDL_sysvideo.h"
28 #include "SDL_syswm.h"
29 #include "SDL_log.h"
30 #include "SDL_hints.h"
31 #include "../../events/SDL_mouse_c.h"
32 #include "../../events/SDL_keyboard_c.h"
33 
34 #ifdef SDL_INPUT_LINUXEV
35 #include "../../core/linux/SDL_evdev.h"
36 #endif
37 
38 /* KMS/DRM declarations */
39 #include "SDL_kmsdrmvideo.h"
40 #include "SDL_kmsdrmevents.h"
41 #include "SDL_kmsdrmopengles.h"
42 #include "SDL_kmsdrmmouse.h"
43 #include "SDL_kmsdrmdyn.h"
44 #include <sys/stat.h>
45 #include <dirent.h>
46 #include <errno.h>
47 
48 #define KMSDRM_DRI_PATH "/dev/dri/"
49 
50 static int
51 check_modestting(int devindex)
52 {
54  char device[512];
55  int drm_fd;
56 
57  SDL_snprintf(device, sizeof (device), "%scard%d", KMSDRM_DRI_PATH, devindex);
58 
59  drm_fd = open(device, O_RDWR | O_CLOEXEC);
60  if (drm_fd >= 0) {
61  if (SDL_KMSDRM_LoadSymbols()) {
62  drmModeRes *resources = KMSDRM_drmModeGetResources(drm_fd);
63  if (resources != NULL) {
64  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "%scard%d connector, encoder and CRTC counts are: %d %d %d",
65  KMSDRM_DRI_PATH, devindex,
66  resources->count_connectors, resources->count_encoders, resources->count_crtcs);
67 
68  if (resources->count_connectors > 0 && resources->count_encoders > 0 && resources->count_crtcs > 0) {
70  }
71  KMSDRM_drmModeFreeResources(resources);
72  }
74  }
75  close(drm_fd);
76  }
77 
78  return available;
79 }
80 
81 static int get_dricount(void)
82 {
83  int devcount = 0;
84  struct dirent *res;
85  struct stat sb;
86  DIR *folder;
87 
88  if (!(stat(KMSDRM_DRI_PATH, &sb) == 0
89  && S_ISDIR(sb.st_mode))) {
90  printf("The path %s cannot be opened or is not available\n",
91  KMSDRM_DRI_PATH);
92  return 0;
93  }
94 
95  if (access(KMSDRM_DRI_PATH, F_OK) == -1) {
96  printf("The path %s cannot be opened\n",
97  KMSDRM_DRI_PATH);
98  return 0;
99  }
100 
101  folder = opendir(KMSDRM_DRI_PATH);
102  if (folder) {
103  while ((res = readdir(folder))) {
104  int len = SDL_strlen(res->d_name);
105  if (len > 4 && SDL_strncmp(res->d_name, "card", 4) == 0) {
106  devcount++;
107  }
108  }
109  closedir(folder);
110  }
111 
112  return devcount;
113 }
114 
115 static int
116 get_driindex(void)
117 {
118  const int devcount = get_dricount();
119  int i;
120 
121  for (i = 0; i < devcount; i++) {
122  if (check_modestting(i)) {
123  return i;
124  }
125  }
126 
127  return -ENOENT;
128 }
129 
130 static int
131 KMSDRM_Available(void)
132 {
133  int ret = -ENOENT;
134 
135  ret = get_driindex();
136  if (ret >= 0)
137  return 1;
138 
139  return ret;
140 }
141 
142 static void
143 KMSDRM_Destroy(SDL_VideoDevice * device)
144 {
145  if (device->driverdata != NULL) {
146  SDL_free(device->driverdata);
147  device->driverdata = NULL;
148  }
149 
150  SDL_free(device);
152 }
153 
154 static SDL_VideoDevice *
155 KMSDRM_Create(int devindex)
156 {
158  SDL_VideoData *vdata;
159 
160  if (!devindex || (devindex > 99)) {
161  devindex = get_driindex();
162  }
163 
164  if (devindex < 0) {
165  SDL_SetError("devindex (%d) must be between 0 and 99.\n", devindex);
166  return NULL;
167  }
168 
169  if (!SDL_KMSDRM_LoadSymbols()) {
170  return NULL;
171  }
172 
173  /* Initialize SDL_VideoDevice structure */
175  if (device == NULL) {
176  SDL_OutOfMemory();
177  return NULL;
178  }
179 
180  /* Initialize internal data */
181  vdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
182  if (vdata == NULL) {
183  SDL_OutOfMemory();
184  goto cleanup;
185  }
186  vdata->devindex = devindex;
187  vdata->drm_fd = -1;
188 
189  device->driverdata = vdata;
190 
191  /* Setup amount of available displays and current display */
192  device->num_displays = 0;
193 
194  /* Set device free function */
195  device->free = KMSDRM_Destroy;
196 
197  /* Setup all functions which we can handle */
198  device->VideoInit = KMSDRM_VideoInit;
199  device->VideoQuit = KMSDRM_VideoQuit;
200  device->GetDisplayModes = KMSDRM_GetDisplayModes;
201  device->SetDisplayMode = KMSDRM_SetDisplayMode;
202  device->CreateSDLWindow = KMSDRM_CreateWindow;
203  device->CreateSDLWindowFrom = KMSDRM_CreateWindowFrom;
204  device->SetWindowTitle = KMSDRM_SetWindowTitle;
205  device->SetWindowIcon = KMSDRM_SetWindowIcon;
206  device->SetWindowPosition = KMSDRM_SetWindowPosition;
207  device->SetWindowSize = KMSDRM_SetWindowSize;
208  device->ShowWindow = KMSDRM_ShowWindow;
209  device->HideWindow = KMSDRM_HideWindow;
210  device->RaiseWindow = KMSDRM_RaiseWindow;
211  device->MaximizeWindow = KMSDRM_MaximizeWindow;
212  device->MinimizeWindow = KMSDRM_MinimizeWindow;
213  device->RestoreWindow = KMSDRM_RestoreWindow;
214  device->SetWindowGrab = KMSDRM_SetWindowGrab;
215  device->DestroyWindow = KMSDRM_DestroyWindow;
216  device->GetWindowWMInfo = KMSDRM_GetWindowWMInfo;
217 #if SDL_VIDEO_OPENGL_EGL
218  device->GL_LoadLibrary = KMSDRM_GLES_LoadLibrary;
219  device->GL_GetProcAddress = KMSDRM_GLES_GetProcAddress;
220  device->GL_UnloadLibrary = KMSDRM_GLES_UnloadLibrary;
221  device->GL_CreateContext = KMSDRM_GLES_CreateContext;
222  device->GL_MakeCurrent = KMSDRM_GLES_MakeCurrent;
223  device->GL_SetSwapInterval = KMSDRM_GLES_SetSwapInterval;
224  device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval;
225  device->GL_SwapWindow = KMSDRM_GLES_SwapWindow;
226  device->GL_DeleteContext = KMSDRM_GLES_DeleteContext;
227 #endif
228 
229  device->PumpEvents = KMSDRM_PumpEvents;
230 
231  return device;
232 
233 cleanup:
234  if (device != NULL)
235  SDL_free(device);
236  if (vdata != NULL)
237  SDL_free(vdata);
238  return NULL;
239 }
240 
242  "KMSDRM",
243  "KMS/DRM Video Driver",
244  KMSDRM_Available,
245  KMSDRM_Create
246 };
247 
248 
249 static void
250 KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data)
251 {
252  KMSDRM_FBInfo *fb_info = (KMSDRM_FBInfo *)data;
253 
254  if (fb_info && fb_info->drm_fd >= 0 && fb_info->fb_id != 0) {
255  KMSDRM_drmModeRmFB(fb_info->drm_fd, fb_info->fb_id);
256  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Delete DRM FB %u", fb_info->fb_id);
257  }
258 
259  SDL_free(fb_info);
260 }
261 
263 KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
264 {
265  uint32_t w, h, stride, handle;
266  int ret;
268  KMSDRM_FBInfo *fb_info;
269 
270  fb_info = (KMSDRM_FBInfo *)KMSDRM_gbm_bo_get_user_data(bo);
271  if (fb_info != NULL) {
272  /* Have a previously used framebuffer, return it */
273  return fb_info;
274  }
275 
276  /* Here a new DRM FB must be created */
277  fb_info = (KMSDRM_FBInfo *)SDL_calloc(1, sizeof(KMSDRM_FBInfo));
278  if (fb_info == NULL) {
279  SDL_OutOfMemory();
280  return NULL;
281  }
282  fb_info->drm_fd = vdata->drm_fd;
283 
284  w = KMSDRM_gbm_bo_get_width(bo);
285  h = KMSDRM_gbm_bo_get_height(bo);
286  stride = KMSDRM_gbm_bo_get_stride(bo);
287  handle = KMSDRM_gbm_bo_get_handle(bo).u32;
288 
289  ret = KMSDRM_drmModeAddFB(vdata->drm_fd, w, h, 24, 32, stride, handle, &fb_info->fb_id);
290  if (ret < 0) {
291  SDL_free(fb_info);
292  return NULL;
293  }
294  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "New DRM FB (%u): %ux%u, stride %u from BO %p", fb_info->fb_id, w, h, stride, (void *)bo);
295 
296  /* Associate our DRM framebuffer with this buffer object */
297  KMSDRM_gbm_bo_set_user_data(bo, fb_info, KMSDRM_FBDestroyCallback);
298  return fb_info;
299 }
300 
301 SDL_bool
304 
305  while (wdata->waiting_for_flip) {
306  vdata->drm_pollfd.revents = 0;
307  if (poll(&vdata->drm_pollfd, 1, timeout) < 0) {
308  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error");
309  return SDL_FALSE;
310  }
311 
312  if (vdata->drm_pollfd.revents & (POLLHUP | POLLERR)) {
313  SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll hup or error");
314  return SDL_FALSE;
315  }
316 
317  if (vdata->drm_pollfd.revents & POLLIN) {
318  /* Page flip? If so, drmHandleEvent will unset wdata->waiting_for_flip */
319  KMSDRM_drmHandleEvent(vdata->drm_fd, &vdata->drm_evctx);
320  } else {
321  /* Timed out and page flip didn't happen */
322  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Dropping frame while waiting_for_flip");
323  return SDL_FALSE;
324  }
325  }
326  return SDL_TRUE;
327 }
328 
329 static void
330 KMSDRM_FlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data)
331 {
332  *((SDL_bool *) data) = SDL_FALSE;
333 }
334 
335 
336 /*****************************************************************************/
337 /* SDL Video and Display initialization/handling functions */
338 /* _this is a SDL_VideoDevice * */
339 /*****************************************************************************/
340 int
342 {
343  int i, j;
344  SDL_bool found;
345  int ret = 0;
346  char *devname;
348  drmModeRes *resources = NULL;
349  drmModeConnector *connector = NULL;
350  drmModeEncoder *encoder = NULL;
351  SDL_DisplayMode current_mode;
352  SDL_VideoDisplay display;
353 
354  /* Allocate display internal data */
356  if (data == NULL) {
357  return SDL_OutOfMemory();
358  }
359 
360  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoInit()");
361 
362  /* Open /dev/dri/cardNN */
363  devname = (char *) SDL_calloc(1, 16);
364  if (devname == NULL) {
365  ret = SDL_OutOfMemory();
366  goto cleanup;
367  }
368  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opening device /dev/dri/card%d", vdata->devindex);
369  SDL_snprintf(devname, 16, "/dev/dri/card%d", vdata->devindex);
370  vdata->drm_fd = open(devname, O_RDWR | O_CLOEXEC);
371  SDL_free(devname);
372 
373  if (vdata->drm_fd < 0) {
374  ret = SDL_SetError("Could not open /dev/dri/card%d.", vdata->devindex);
375  goto cleanup;
376  }
377  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opened DRM FD (%d)", vdata->drm_fd);
378 
379  vdata->gbm = KMSDRM_gbm_create_device(vdata->drm_fd);
380  if (vdata->gbm == NULL) {
381  ret = SDL_SetError("Couldn't create gbm device.");
382  goto cleanup;
383  }
384 
385  /* Find the first available connector with modes */
386  resources = KMSDRM_drmModeGetResources(vdata->drm_fd);
387  if (!resources) {
388  ret = SDL_SetError("drmModeGetResources(%d) failed", vdata->drm_fd);
389  goto cleanup;
390  }
391 
392  for (i = 0; i < resources->count_connectors; i++) {
393  connector = KMSDRM_drmModeGetConnector(vdata->drm_fd, resources->connectors[i]);
394  if (connector == NULL)
395  continue;
396 
397  if (connector->connection == DRM_MODE_CONNECTED &&
398  connector->count_modes > 0) {
399  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found connector %d with %d modes.",
400  connector->connector_id, connector->count_modes);
401  vdata->saved_conn_id = connector->connector_id;
402  break;
403  }
404 
405  KMSDRM_drmModeFreeConnector(connector);
406  connector = NULL;
407  }
408 
409  if (i == resources->count_connectors) {
410  ret = SDL_SetError("No currently active connector found.");
411  goto cleanup;
412  }
413 
414  found = SDL_FALSE;
415 
416  for (i = 0; i < resources->count_encoders; i++) {
417  encoder = KMSDRM_drmModeGetEncoder(vdata->drm_fd, resources->encoders[i]);
418 
419  if (encoder == NULL)
420  continue;
421 
422  if (encoder->encoder_id == connector->encoder_id) {
423  data->encoder_id = encoder->encoder_id;
424  found = SDL_TRUE;
425  } else {
426  for (j = 0; j < connector->count_encoders; j++) {
427  if (connector->encoders[j] == encoder->encoder_id) {
428  data->encoder_id = encoder->encoder_id;
429  found = SDL_TRUE;
430  break;
431  }
432  }
433  }
434 
435  if (found == SDL_TRUE) {
436  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found encoder %d.", data->encoder_id);
437  break;
438  }
439 
440  KMSDRM_drmModeFreeEncoder(encoder);
441  encoder = NULL;
442  }
443 
444  if (i == resources->count_encoders) {
445  ret = SDL_SetError("No connected encoder found.");
446  goto cleanup;
447  }
448 
449  vdata->saved_crtc = KMSDRM_drmModeGetCrtc(vdata->drm_fd, encoder->crtc_id);
450 
451  if (vdata->saved_crtc == NULL) {
452  for (i = 0; i < resources->count_crtcs; i++) {
453  if (encoder->possible_crtcs & (1 << i)) {
454  encoder->crtc_id = resources->crtcs[i];
455  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Set encoder's CRTC to %d.", encoder->crtc_id);
456  vdata->saved_crtc = KMSDRM_drmModeGetCrtc(vdata->drm_fd, encoder->crtc_id);
457  break;
458  }
459  }
460  }
461 
462  if (vdata->saved_crtc == NULL) {
463  ret = SDL_SetError("No CRTC found.");
464  goto cleanup;
465  }
466  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Saved crtc_id %u, fb_id %u, (%u,%u), %ux%u",
467  vdata->saved_crtc->crtc_id, vdata->saved_crtc->buffer_id, vdata->saved_crtc->x,
468  vdata->saved_crtc->y, vdata->saved_crtc->width, vdata->saved_crtc->height);
469  data->crtc_id = encoder->crtc_id;
470  data->cur_mode = vdata->saved_crtc->mode;
471  vdata->crtc_id = encoder->crtc_id;
472 
473  // select default mode if this one is not valid
474  if (vdata->saved_crtc->mode_valid == 0) {
476  "Current mode is invalid, selecting connector's mode #0.");
477  data->cur_mode = connector->modes[0];
478  }
479 
480  SDL_zero(current_mode);
481 
482  current_mode.w = data->cur_mode.hdisplay;
483  current_mode.h = data->cur_mode.vdisplay;
484  current_mode.refresh_rate = data->cur_mode.vrefresh;
485 
486  /* FIXME ?
487  drmModeFB *fb = drmModeGetFB(vdata->drm_fd, vdata->saved_crtc->buffer_id);
488  current_mode.format = drmToSDLPixelFormat(fb->bpp, fb->depth);
489  drmModeFreeFB(fb);
490  */
491  current_mode.format = SDL_PIXELFORMAT_ARGB8888;
492 
493  current_mode.driverdata = NULL;
494 
495  SDL_zero(display);
496  display.desktop_mode = current_mode;
497  display.current_mode = current_mode;
498 
499  display.driverdata = data;
500  /* SDL_VideoQuit will later SDL_free(display.driverdata) */
501  SDL_AddVideoDisplay(&display);
502 
503  /* Setup page flip handler */
504  vdata->drm_pollfd.fd = vdata->drm_fd;
505  vdata->drm_pollfd.events = POLLIN;
506  vdata->drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
507  vdata->drm_evctx.page_flip_handler = KMSDRM_FlipHandler;
508 
509 #ifdef SDL_INPUT_LINUXEV
510  SDL_EVDEV_Init();
511 #endif
512 
514 
515  return ret;
516 
517 cleanup:
518  if (encoder != NULL)
519  KMSDRM_drmModeFreeEncoder(encoder);
520  if (connector != NULL)
521  KMSDRM_drmModeFreeConnector(connector);
522  if (resources != NULL)
523  KMSDRM_drmModeFreeResources(resources);
524 
525  if (ret != 0) {
526  /* Error (complete) cleanup */
527  SDL_free(data);
528  if(vdata->saved_crtc != NULL) {
529  KMSDRM_drmModeFreeCrtc(vdata->saved_crtc);
530  vdata->saved_crtc = NULL;
531  }
532  if (vdata->gbm != NULL) {
533  KMSDRM_gbm_device_destroy(vdata->gbm);
534  vdata->gbm = NULL;
535  }
536  if (vdata->drm_fd >= 0) {
537  close(vdata->drm_fd);
538  vdata->drm_fd = -1;
539  }
540  }
541  return ret;
542 }
543 
544 void
546 {
548 
549  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoQuit()");
550 
553  }
554 
555  if(vdata->saved_crtc != NULL) {
556  if(vdata->drm_fd >= 0 && vdata->saved_conn_id > 0) {
557  /* Restore saved CRTC settings */
558  drmModeCrtc *crtc = vdata->saved_crtc;
559  if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, crtc->crtc_id, crtc->buffer_id,
560  crtc->x, crtc->y, &vdata->saved_conn_id, 1,
561  &crtc->mode) != 0) {
562  SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original CRTC mode");
563  }
564  }
565  KMSDRM_drmModeFreeCrtc(vdata->saved_crtc);
566  vdata->saved_crtc = NULL;
567  }
568  if (vdata->gbm != NULL) {
569  KMSDRM_gbm_device_destroy(vdata->gbm);
570  vdata->gbm = NULL;
571  }
572  if (vdata->drm_fd >= 0) {
573  close(vdata->drm_fd);
574  SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Closed DRM FD %d", vdata->drm_fd);
575  vdata->drm_fd = -1;
576  }
577 #ifdef SDL_INPUT_LINUXEV
578  SDL_EVDEV_Quit();
579 #endif
580 }
581 
582 void
584 {
585  /* Only one display mode available, the current one */
586  SDL_AddDisplayMode(display, &display->current_mode);
587 }
588 
589 int
591 {
592  return 0;
593 }
594 
595 int
597 {
598  SDL_WindowData *wdata;
599  SDL_VideoDisplay *display;
601  Uint32 surface_fmt, surface_flags;
602 
603  /* Allocate window internal data */
604  wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
605  if (wdata == NULL) {
606  SDL_OutOfMemory();
607  goto error;
608  }
609 
610  wdata->waiting_for_flip = SDL_FALSE;
611  display = SDL_GetDisplayForWindow(window);
612 
613  /* Windows have one size for now */
614  window->w = display->desktop_mode.w;
615  window->h = display->desktop_mode.h;
616 
617  /* Maybe you didn't ask for a fullscreen OpenGL window, but that's what you get */
619 
620  surface_fmt = GBM_FORMAT_XRGB8888;
621  surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
622 
623  if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, surface_fmt, surface_flags)) {
624  SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "GBM surface format not supported. Trying anyway.");
625  }
626  wdata->gs = KMSDRM_gbm_surface_create(vdata->gbm, window->w, window->h, surface_fmt, surface_flags);
627 
628 #if SDL_VIDEO_OPENGL_EGL
629  if (!_this->egl_data) {
630  if (SDL_GL_LoadLibrary(NULL) < 0) {
631  goto error;
632  }
633  }
634  SDL_EGL_SetRequiredVisualId(_this, surface_fmt);
635  wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wdata->gs);
636 
637  if (wdata->egl_surface == EGL_NO_SURFACE) {
638  SDL_SetError("Could not create EGL window surface");
639  goto error;
640  }
641 #endif /* SDL_VIDEO_OPENGL_EGL */
642 
643  /* In case we want low-latency, double-buffer video, we take note here */
644  wdata->double_buffer = SDL_FALSE;
646  wdata->double_buffer = SDL_TRUE;
647  }
648 
649  /* Window is created, but we have yet to set up CRTC to one of the GBM buffers if we want
650  drmModePageFlip to work, and we can't do it until EGL is completely setup, because we
651  need to do eglSwapBuffers so we can get a valid GBM buffer object to call
652  drmModeSetCrtc on it. */
653  wdata->crtc_ready = SDL_FALSE;
654 
655  /* Setup driver data for this window */
656  window->driverdata = wdata;
657 
658  /* One window, it always has focus */
661 
662  /* Window has been successfully created */
663  return 0;
664 
665 error:
666  if (wdata != NULL) {
667 #if SDL_VIDEO_OPENGL_EGL
668  if (wdata->egl_surface != EGL_NO_SURFACE)
669  SDL_EGL_DestroySurface(_this, wdata->egl_surface);
670 #endif /* SDL_VIDEO_OPENGL_EGL */
671  if (wdata->gs != NULL)
672  KMSDRM_gbm_surface_destroy(wdata->gs);
673  SDL_free(wdata);
674  }
675  return -1;
676 }
677 
678 void
680 {
681  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
682  if(data) {
683  /* Wait for any pending page flips and unlock buffer */
685  if (data->crtc_bo != NULL) {
686  KMSDRM_gbm_surface_release_buffer(data->gs, data->crtc_bo);
687  data->crtc_bo = NULL;
688  }
689  if (data->next_bo != NULL) {
690  KMSDRM_gbm_surface_release_buffer(data->gs, data->next_bo);
691  data->next_bo = NULL;
692  }
693  if (data->current_bo != NULL) {
694  KMSDRM_gbm_surface_release_buffer(data->gs, data->current_bo);
695  data->current_bo = NULL;
696  }
697 #if SDL_VIDEO_OPENGL_EGL
698  SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT);
699  if (data->egl_surface != EGL_NO_SURFACE) {
700  SDL_EGL_DestroySurface(_this, data->egl_surface);
701  }
702 #endif /* SDL_VIDEO_OPENGL_EGL */
703  if (data->gs != NULL) {
704  KMSDRM_gbm_surface_destroy(data->gs);
705  data->gs = NULL;
706  }
707  SDL_free(data);
708  window->driverdata = NULL;
709  }
710 }
711 
712 int
714 {
715  return -1;
716 }
717 
718 void
720 {
721 }
722 void
724 {
725 }
726 void
728 {
729 }
730 void
732 {
733 }
734 void
736 {
737 }
738 void
740 {
741 }
742 void
744 {
745 }
746 void
748 {
749 }
750 void
752 {
753 }
754 void
756 {
757 }
758 void
760 {
761 
762 }
763 
764 /*****************************************************************************/
765 /* SDL Window Manager function */
766 /*****************************************************************************/
767 SDL_bool
769 {
770  if (info->version.major <= SDL_MAJOR_VERSION) {
771  return SDL_TRUE;
772  } else {
773  SDL_SetError("application not compiled with SDL %d.%d\n",
775  return SDL_FALSE;
776  }
777 
778  /* Failed to get window manager information */
779  return SDL_FALSE;
780 }
781 
782 #endif /* SDL_VIDEO_DRIVER_KMSDRM */
783 
784 /* vi: set ts=4 sw=4 expandtab: */
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
KMSDRM_GLES_GetProcAddress
void * KMSDRM_GLES_GetProcAddress(_THIS, const char *proc)
KMSDRM_DestroyWindow
void KMSDRM_DestroyWindow(_THIS, SDL_Window *window)
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
SDL_DisplayMode::format
Uint32 format
Definition: SDL_video.h:55
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:381
KMSDRM_SetDisplayMode
int KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:70
SDL_VideoData::drm_pollfd
struct pollfd drm_pollfd
Definition: SDL_kmsdrmvideo.h:45
KMSDRM_SetWindowSize
void KMSDRM_SetWindowSize(_THIS, SDL_Window *window)
SDL_kmsdrmvideo.h
NULL
#define NULL
Definition: begin_code.h:167
handle
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
KMSDRM_FBInfo
Definition: SDL_kmsdrmvideo.h:74
timeout
GLbitfield GLuint64 timeout
Definition: SDL_opengl_glext.h:1483
access
GLuint GLint GLboolean GLint GLenum access
Definition: SDL_opengl_glext.h:2162
mode
GLenum mode
Definition: SDL_opengl_glext.h:1122
NativeWindowType
EGLNativeWindowType NativeWindowType
Definition: eglplatform.h:112
SDL_SysWMinfo
Definition: SDL_syswm.h:197
SDL_log.h
SDL_WindowData
Definition: SDL_androidwindow.h:38
SDL_VideoData::saved_crtc
drmModeCrtc * saved_crtc
Definition: SDL_kmsdrmvideo.h:46
SDL_GetDisplayForWindow
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1089
SDL_WINDOW_FULLSCREEN
@ SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:100
SDL_WINDOW_OPENGL
@ SDL_WINDOW_OPENGL
Definition: SDL_video.h:101
KMSDRM_MaximizeWindow
void KMSDRM_MaximizeWindow(_THIS, SDL_Window *window)
KMSDRM_GLES_LoadLibrary
int KMSDRM_GLES_LoadLibrary(_THIS, const char *path)
KMSDRM_GLES_SetSwapInterval
int KMSDRM_GLES_SetSwapInterval(_THIS, int interval)
KMSDRM_InitMouse
void KMSDRM_InitMouse(_THIS)
SDL_GL_LoadLibrary
#define SDL_GL_LoadLibrary
Definition: SDL_dynapi_overrides.h:553
SDL_SetKeyboardFocus
void SDL_SetKeyboardFocus(SDL_Window *window)
Definition: SDL_keyboard.c:630
KMSDRM_CreateWindowFrom
int KMSDRM_CreateWindowFrom(_THIS, SDL_Window *window, const void *data)
SDL_VideoDisplay::desktop_mode
SDL_DisplayMode desktop_mode
Definition: SDL_sysvideo.h:131
SDL_strncmp
#define SDL_strncmp
Definition: SDL_dynapi_overrides.h:418
KMSDRM_CreateWindow
int KMSDRM_CreateWindow(_THIS, SDL_Window *window)
SDL_VideoData::crtc_id
uint32_t crtc_id
Definition: SDL_kmsdrmvideo.h:48
h
GLfloat GLfloat GLfloat GLfloat h
Definition: SDL_opengl_glext.h:1946
SDL_kmsdrmmouse.h
SDL_SetMouseFocus
void SDL_SetMouseFocus(SDL_Window *window)
Definition: SDL_mouse.c:211
SDL_LogError
#define SDL_LogError
Definition: SDL_dynapi_overrides.h:36
SDL_DisplayMode::h
int h
Definition: SDL_video.h:57
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
EGL_NO_CONTEXT
#define EGL_NO_CONTEXT
Definition: egl.h:98
KMSDRM_GLES_UnloadLibrary
void KMSDRM_GLES_UnloadLibrary(_THIS)
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
SDL_DisplayMode
The structure that defines a display mode.
Definition: SDL_video.h:53
SDL_AddDisplayMode
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
Definition: SDL_video.c:751
SDL_GL_UnloadLibrary
#define SDL_GL_UnloadLibrary
Definition: SDL_dynapi_overrides.h:555
KMSDRM_GLES_CreateContext
SDL_GLContext KMSDRM_GLES_CreateContext(_THIS, SDL_Window *window)
SDL_WindowData::gs
struct gbm_surface * gs
Definition: SDL_kmsdrmvideo.h:62
cleanup
static void cleanup(void)
Definition: testfile.c:44
len
GLenum GLsizei len
Definition: SDL_opengl_glext.h:2926
SDL_GetHintBoolean
#define SDL_GetHintBoolean
Definition: SDL_dynapi_overrides.h:608
SDL_KMSDRM_UnloadSymbols
void SDL_KMSDRM_UnloadSymbols(void)
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_VideoData::gbm
struct gbm_device * gbm
Definition: SDL_kmsdrmvideo.h:43
SDL_WindowData::crtc_ready
SDL_bool crtc_ready
Definition: SDL_kmsdrmvideo.h:67
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
KMSDRM_PumpEvents
void KMSDRM_PumpEvents(_THIS)
SDL_kmsdrmevents.h
SDL_MINOR_VERSION
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
EGL_NO_SURFACE
#define EGL_NO_SURFACE
Definition: egl.h:100
KMSDRM_bootstrap
VideoBootStrap KMSDRM_bootstrap
KMSDRM_SetWindowGrab
void KMSDRM_SetWindowGrab(_THIS, SDL_Window *window, SDL_bool grabbed)
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_VideoDevice::driver_loaded
int driver_loaded
Definition: SDL_sysvideo.h:353
SDL_DisplayMode::refresh_rate
int refresh_rate
Definition: SDL_video.h:58
SDL_LogDebug
#define SDL_LogDebug
Definition: SDL_dynapi_overrides.h:33
frame
int frame
Definition: teststreaming.c:60
SDL_LOG_CATEGORY_VIDEO
@ SDL_LOG_CATEGORY_VIDEO
Definition: SDL_log.h:71
KMSDRM_VideoInit
int KMSDRM_VideoInit(_THIS)
KMSDRM_FBInfo::drm_fd
int drm_fd
Definition: SDL_kmsdrmvideo.h:76
SDL_kmsdrmopengles.h
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
KMSDRM_GLES_MakeCurrent
int KMSDRM_GLES_MakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context)
SDL_PIXELFORMAT_ARGB8888
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
SDL_DisplayMode::w
int w
Definition: SDL_video.h:56
SDL_AddVideoDisplay
int SDL_AddVideoDisplay(const SDL_VideoDisplay *display)
Definition: SDL_video.c:603
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_VideoDevice
Definition: SDL_sysvideo.h:148
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_VideoData::drm_fd
int drm_fd
Definition: SDL_kmsdrmvideo.h:42
KMSDRM_RestoreWindow
void KMSDRM_RestoreWindow(_THIS, SDL_Window *window)
KMSDRM_SetWindowPosition
void KMSDRM_SetWindowPosition(_THIS, SDL_Window *window)
available
static int available()
Definition: video.c:356
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
KMSDRM_RaiseWindow
void KMSDRM_RaiseWindow(_THIS, SDL_Window *window)
KMSDRM_SetWindowIcon
void KMSDRM_SetWindowIcon(_THIS, SDL_Window *window, SDL_Surface *icon)
KMSDRM_HideWindow
void KMSDRM_HideWindow(_THIS, SDL_Window *window)
SDL_WindowData::double_buffer
SDL_bool double_buffer
Definition: SDL_kmsdrmvideo.h:68
uint32_t
unsigned int uint32_t
Definition: SDL_config_windows.h:63
SDL_WindowData::waiting_for_flip
SDL_bool waiting_for_flip
Definition: SDL_kmsdrmvideo.h:66
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
KMSDRM_GetWindowWMInfo
SDL_bool KMSDRM_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
SDL_SysWMinfo::version
SDL_version version
Definition: SDL_syswm.h:199
SDL_VideoDisplay
Definition: SDL_sysvideo.h:125
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_snprintf
#define SDL_snprintf
Definition: SDL_dynapi_overrides.h:40
j
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
Definition: SDL_x11sym.h:50
SDL_VideoData::drm_evctx
drmEventContext drm_evctx
Definition: SDL_kmsdrmvideo.h:44
SDL_kmsdrmdyn.h
SDL_hints.h
KMSDRM_GLES_DeleteContext
void KMSDRM_GLES_DeleteContext(_THIS, SDL_GLContext context)
SDL_HINT_VIDEO_DOUBLE_BUFFER
#define SDL_HINT_VIDEO_DOUBLE_BUFFER
Tell the video driver that we only want a double buffer.
Definition: SDL_hints.h:993
KMSDRM_FBFromBO
KMSDRM_FBInfo * KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
SDL_strlen
#define SDL_strlen
Definition: SDL_dynapi_overrides.h:393
stride
GLsizei stride
Definition: SDL_opengl_glext.h:378
KMSDRM_ShowWindow
void KMSDRM_ShowWindow(_THIS, SDL_Window *window)
KMSDRM_GLES_SwapWindow
int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window *window)
KMSDRM_MinimizeWindow
void KMSDRM_MinimizeWindow(_THIS, SDL_Window *window)
KMSDRM_SetWindowTitle
void KMSDRM_SetWindowTitle(_THIS, SDL_Window *window)
KMSDRM_GetDisplayModes
void KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
SDL_DisplayMode::driverdata
void * driverdata
Definition: SDL_video.h:59
SDL_KMSDRM_LoadSymbols
int SDL_KMSDRM_LoadSymbols(void)
SDL_VideoDisplay::current_mode
SDL_DisplayMode current_mode
Definition: SDL_sysvideo.h:132
fd
GLuint64 GLenum GLint fd
Definition: gl2ext.h:1508
SDL_version::major
Uint8 major
Definition: SDL_version.h:53
res
GLuint res
Definition: SDL_opengl_glext.h:7937
VideoBootStrap
Definition: SDL_sysvideo.h:397
SDL_MAJOR_VERSION
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
device
static SDL_AudioDeviceID device
Definition: loopwave.c:37
SDL_LogWarn
#define SDL_LogWarn
Definition: SDL_dynapi_overrides.h:35
SDL_WindowData::egl_surface
EGLSurface egl_surface
Definition: SDL_androidwindow.h:40
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_VideoData::devindex
int devindex
Definition: SDL_kmsdrmvideo.h:41
KMSDRM_VideoQuit
void KMSDRM_VideoQuit(_THIS)
KMSDRM_GLES_GetSwapInterval
int KMSDRM_GLES_GetSwapInterval(_THIS)
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
SDL_syswm.h
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
KMSDRM_FBInfo::fb_id
uint32_t fb_id
Definition: SDL_kmsdrmvideo.h:77
SDL_VideoDevice::gl_config
struct SDL_VideoDevice::@261 gl_config