| /* |
| Simple DirectMedia Layer |
| Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org> |
| |
| This software is provided 'as-is', without any express or implied |
| warranty. In no event will the authors be held liable for any damages |
| arising from the use of this software. |
| |
| Permission is granted to anyone to use this software for any purpose, |
| including commercial applications, and to alter it and redistribute it |
| freely, subject to the following restrictions: |
| |
| 1. The origin of this software must not be misrepresented; you must not |
| claim that you wrote the original software. If you use this software |
| in a product, an acknowledgment in the product documentation would be |
| appreciated but is not required. |
| 2. Altered source versions must be plainly marked as such, and must not be |
| misrepresented as being the original software. |
| 3. This notice may not be removed or altered from any source distribution. |
| */ |
| |
| #include "../../SDL_internal.h" |
| |
| #if SDL_VIDEO_DRIVER_KMSDRM |
| |
| /* SDL internals */ |
| #include "../SDL_sysvideo.h" |
| #include "SDL_syswm.h" |
| #include "SDL_log.h" |
| #include "SDL_hints.h" |
| #include "../../events/SDL_mouse_c.h" |
| #include "../../events/SDL_keyboard_c.h" |
| |
| #ifdef SDL_INPUT_LINUXEV |
| #include "../../core/linux/SDL_evdev.h" |
| #endif |
| |
| /* KMS/DRM declarations */ |
| #include "SDL_kmsdrmvideo.h" |
| #include "SDL_kmsdrmevents.h" |
| #include "SDL_kmsdrmopengles.h" |
| #include "SDL_kmsdrmmouse.h" |
| #include "SDL_kmsdrmdyn.h" |
| #include <sys/stat.h> |
| #include <dirent.h> |
| #include <errno.h> |
| |
| #define KMSDRM_DRI_PATH "/dev/dri/" |
| |
| static int |
| check_modestting(int devindex) |
| { |
| SDL_bool available = SDL_FALSE; |
| char device[512]; |
| int drm_fd; |
| |
| SDL_snprintf(device, sizeof (device), "%scard%d", KMSDRM_DRI_PATH, devindex); |
| |
| drm_fd = open(device, O_RDWR | O_CLOEXEC); |
| if (drm_fd >= 0) { |
| if (SDL_KMSDRM_LoadSymbols()) { |
| drmModeRes *resources = KMSDRM_drmModeGetResources(drm_fd); |
| if (resources != NULL) { |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "%scard%d connector, encoder and CRTC counts are: %d %d %d", |
| KMSDRM_DRI_PATH, devindex, |
| resources->count_connectors, resources->count_encoders, resources->count_crtcs); |
| |
| if (resources->count_connectors > 0 && resources->count_encoders > 0 && resources->count_crtcs > 0) { |
| available = SDL_TRUE; |
| } |
| KMSDRM_drmModeFreeResources(resources); |
| } |
| SDL_KMSDRM_UnloadSymbols(); |
| } |
| close(drm_fd); |
| } |
| |
| return available; |
| } |
| |
| static int get_dricount(void) |
| { |
| int devcount = 0; |
| struct dirent *res; |
| struct stat sb; |
| DIR *folder; |
| |
| if (!(stat(KMSDRM_DRI_PATH, &sb) == 0 |
| && S_ISDIR(sb.st_mode))) { |
| printf("The path %s cannot be opened or is not available\n", |
| KMSDRM_DRI_PATH); |
| return 0; |
| } |
| |
| if (access(KMSDRM_DRI_PATH, F_OK) == -1) { |
| printf("The path %s cannot be opened\n", |
| KMSDRM_DRI_PATH); |
| return 0; |
| } |
| |
| folder = opendir(KMSDRM_DRI_PATH); |
| if (folder) { |
| while ((res = readdir(folder))) { |
| if (res->d_type == DT_CHR) { |
| devcount++; |
| } |
| } |
| closedir(folder); |
| } |
| |
| return devcount; |
| } |
| |
| static int |
| get_driindex(void) |
| { |
| const int devcount = get_dricount(); |
| int i; |
| |
| for (i = 0; i < devcount; i++) { |
| if (check_modestting(i)) { |
| return i; |
| } |
| } |
| |
| return -ENOENT; |
| } |
| |
| static int |
| KMSDRM_Available(void) |
| { |
| int ret = -ENOENT; |
| |
| ret = get_driindex(); |
| if (ret >= 0) |
| return 1; |
| |
| return ret; |
| } |
| |
| static void |
| KMSDRM_Destroy(SDL_VideoDevice * device) |
| { |
| if (device->driverdata != NULL) { |
| SDL_free(device->driverdata); |
| device->driverdata = NULL; |
| } |
| |
| SDL_free(device); |
| SDL_KMSDRM_UnloadSymbols(); |
| } |
| |
| static SDL_VideoDevice * |
| KMSDRM_Create(int devindex) |
| { |
| SDL_VideoDevice *device; |
| SDL_VideoData *vdata; |
| |
| if (!devindex || (devindex > 99)) { |
| devindex = get_driindex(); |
| } |
| |
| if (devindex < 0) { |
| SDL_SetError("devindex (%d) must be between 0 and 99.\n", devindex); |
| return NULL; |
| } |
| |
| if (!SDL_KMSDRM_LoadSymbols()) { |
| return NULL; |
| } |
| |
| /* Initialize SDL_VideoDevice structure */ |
| device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); |
| if (device == NULL) { |
| SDL_OutOfMemory(); |
| return NULL; |
| } |
| |
| /* Initialize internal data */ |
| vdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData)); |
| if (vdata == NULL) { |
| SDL_OutOfMemory(); |
| goto cleanup; |
| } |
| vdata->devindex = devindex; |
| vdata->drm_fd = -1; |
| |
| device->driverdata = vdata; |
| |
| /* Setup amount of available displays and current display */ |
| device->num_displays = 0; |
| |
| /* Set device free function */ |
| device->free = KMSDRM_Destroy; |
| |
| /* Setup all functions which we can handle */ |
| device->VideoInit = KMSDRM_VideoInit; |
| device->VideoQuit = KMSDRM_VideoQuit; |
| device->GetDisplayModes = KMSDRM_GetDisplayModes; |
| device->SetDisplayMode = KMSDRM_SetDisplayMode; |
| device->CreateSDLWindow = KMSDRM_CreateWindow; |
| device->CreateSDLWindowFrom = KMSDRM_CreateWindowFrom; |
| device->SetWindowTitle = KMSDRM_SetWindowTitle; |
| device->SetWindowIcon = KMSDRM_SetWindowIcon; |
| device->SetWindowPosition = KMSDRM_SetWindowPosition; |
| device->SetWindowSize = KMSDRM_SetWindowSize; |
| device->ShowWindow = KMSDRM_ShowWindow; |
| device->HideWindow = KMSDRM_HideWindow; |
| device->RaiseWindow = KMSDRM_RaiseWindow; |
| device->MaximizeWindow = KMSDRM_MaximizeWindow; |
| device->MinimizeWindow = KMSDRM_MinimizeWindow; |
| device->RestoreWindow = KMSDRM_RestoreWindow; |
| device->SetWindowGrab = KMSDRM_SetWindowGrab; |
| device->DestroyWindow = KMSDRM_DestroyWindow; |
| device->GetWindowWMInfo = KMSDRM_GetWindowWMInfo; |
| #if SDL_VIDEO_OPENGL_EGL |
| device->GL_LoadLibrary = KMSDRM_GLES_LoadLibrary; |
| device->GL_GetProcAddress = KMSDRM_GLES_GetProcAddress; |
| device->GL_UnloadLibrary = KMSDRM_GLES_UnloadLibrary; |
| device->GL_CreateContext = KMSDRM_GLES_CreateContext; |
| device->GL_MakeCurrent = KMSDRM_GLES_MakeCurrent; |
| device->GL_SetSwapInterval = KMSDRM_GLES_SetSwapInterval; |
| device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval; |
| device->GL_SwapWindow = KMSDRM_GLES_SwapWindow; |
| device->GL_DeleteContext = KMSDRM_GLES_DeleteContext; |
| #endif |
| |
| device->PumpEvents = KMSDRM_PumpEvents; |
| |
| return device; |
| |
| cleanup: |
| if (device != NULL) |
| SDL_free(device); |
| if (vdata != NULL) |
| SDL_free(vdata); |
| return NULL; |
| } |
| |
| VideoBootStrap KMSDRM_bootstrap = { |
| "KMSDRM", |
| "KMS/DRM Video Driver", |
| KMSDRM_Available, |
| KMSDRM_Create |
| }; |
| |
| |
| static void |
| KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data) |
| { |
| KMSDRM_FBInfo *fb_info = (KMSDRM_FBInfo *)data; |
| |
| if (fb_info && fb_info->drm_fd >= 0 && fb_info->fb_id != 0) { |
| KMSDRM_drmModeRmFB(fb_info->drm_fd, fb_info->fb_id); |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Delete DRM FB %u", fb_info->fb_id); |
| } |
| |
| SDL_free(fb_info); |
| } |
| |
| KMSDRM_FBInfo * |
| KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo) |
| { |
| uint32_t w, h, stride, handle; |
| int ret; |
| SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); |
| KMSDRM_FBInfo *fb_info; |
| |
| fb_info = (KMSDRM_FBInfo *)KMSDRM_gbm_bo_get_user_data(bo); |
| if (fb_info != NULL) { |
| /* Have a previously used framebuffer, return it */ |
| return fb_info; |
| } |
| |
| /* Here a new DRM FB must be created */ |
| fb_info = (KMSDRM_FBInfo *)SDL_calloc(1, sizeof(KMSDRM_FBInfo)); |
| if (fb_info == NULL) { |
| SDL_OutOfMemory(); |
| return NULL; |
| } |
| fb_info->drm_fd = vdata->drm_fd; |
| |
| w = KMSDRM_gbm_bo_get_width(bo); |
| h = KMSDRM_gbm_bo_get_height(bo); |
| stride = KMSDRM_gbm_bo_get_stride(bo); |
| handle = KMSDRM_gbm_bo_get_handle(bo).u32; |
| |
| ret = KMSDRM_drmModeAddFB(vdata->drm_fd, w, h, 24, 32, stride, handle, &fb_info->fb_id); |
| if (ret < 0) { |
| SDL_free(fb_info); |
| return NULL; |
| } |
| 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); |
| |
| /* Associate our DRM framebuffer with this buffer object */ |
| KMSDRM_gbm_bo_set_user_data(bo, fb_info, KMSDRM_FBDestroyCallback); |
| return fb_info; |
| } |
| |
| SDL_bool |
| KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *wdata, int timeout) { |
| SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); |
| |
| while (wdata->waiting_for_flip) { |
| vdata->drm_pollfd.revents = 0; |
| if (poll(&vdata->drm_pollfd, 1, timeout) < 0) { |
| SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error"); |
| return SDL_FALSE; |
| } |
| |
| if (vdata->drm_pollfd.revents & (POLLHUP | POLLERR)) { |
| SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll hup or error"); |
| return SDL_FALSE; |
| } |
| |
| if (vdata->drm_pollfd.revents & POLLIN) { |
| /* Page flip? If so, drmHandleEvent will unset wdata->waiting_for_flip */ |
| KMSDRM_drmHandleEvent(vdata->drm_fd, &vdata->drm_evctx); |
| } else { |
| /* Timed out and page flip didn't happen */ |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Dropping frame while waiting_for_flip"); |
| return SDL_FALSE; |
| } |
| } |
| return SDL_TRUE; |
| } |
| |
| static void |
| KMSDRM_FlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) |
| { |
| *((SDL_bool *) data) = SDL_FALSE; |
| } |
| |
| |
| /*****************************************************************************/ |
| /* SDL Video and Display initialization/handling functions */ |
| /* _this is a SDL_VideoDevice * */ |
| /*****************************************************************************/ |
| int |
| KMSDRM_VideoInit(_THIS) |
| { |
| int i, j; |
| SDL_bool found; |
| int ret = 0; |
| char *devname; |
| SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); |
| drmModeRes *resources = NULL; |
| drmModeConnector *connector = NULL; |
| drmModeEncoder *encoder = NULL; |
| SDL_DisplayMode current_mode; |
| SDL_VideoDisplay display; |
| |
| /* Allocate display internal data */ |
| SDL_DisplayData *data = (SDL_DisplayData *) SDL_calloc(1, sizeof(SDL_DisplayData)); |
| if (data == NULL) { |
| return SDL_OutOfMemory(); |
| } |
| |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoInit()"); |
| |
| /* Open /dev/dri/cardNN */ |
| devname = (char *) SDL_calloc(1, 16); |
| if (devname == NULL) { |
| ret = SDL_OutOfMemory(); |
| goto cleanup; |
| } |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opening device /dev/dri/card%d", vdata->devindex); |
| SDL_snprintf(devname, 16, "/dev/dri/card%d", vdata->devindex); |
| vdata->drm_fd = open(devname, O_RDWR | O_CLOEXEC); |
| SDL_free(devname); |
| |
| if (vdata->drm_fd < 0) { |
| ret = SDL_SetError("Could not open /dev/dri/card%d.", vdata->devindex); |
| goto cleanup; |
| } |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opened DRM FD (%d)", vdata->drm_fd); |
| |
| vdata->gbm = KMSDRM_gbm_create_device(vdata->drm_fd); |
| if (vdata->gbm == NULL) { |
| ret = SDL_SetError("Couldn't create gbm device."); |
| goto cleanup; |
| } |
| |
| /* Find the first available connector with modes */ |
| resources = KMSDRM_drmModeGetResources(vdata->drm_fd); |
| if (!resources) { |
| ret = SDL_SetError("drmModeGetResources(%d) failed", vdata->drm_fd); |
| goto cleanup; |
| } |
| |
| for (i = 0; i < resources->count_connectors; i++) { |
| connector = KMSDRM_drmModeGetConnector(vdata->drm_fd, resources->connectors[i]); |
| if (connector == NULL) |
| continue; |
| |
| if (connector->connection == DRM_MODE_CONNECTED && |
| connector->count_modes > 0) { |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found connector %d with %d modes.", |
| connector->connector_id, connector->count_modes); |
| vdata->saved_conn_id = connector->connector_id; |
| break; |
| } |
| |
| KMSDRM_drmModeFreeConnector(connector); |
| connector = NULL; |
| } |
| |
| if (i == resources->count_connectors) { |
| ret = SDL_SetError("No currently active connector found."); |
| goto cleanup; |
| } |
| |
| found = SDL_FALSE; |
| |
| for (i = 0; i < resources->count_encoders; i++) { |
| encoder = KMSDRM_drmModeGetEncoder(vdata->drm_fd, resources->encoders[i]); |
| |
| if (encoder == NULL) |
| continue; |
| |
| if (encoder->encoder_id == connector->encoder_id) { |
| data->encoder_id = encoder->encoder_id; |
| found = SDL_TRUE; |
| } else { |
| for (j = 0; j < connector->count_encoders; j++) { |
| if (connector->encoders[j] == encoder->encoder_id) { |
| data->encoder_id = encoder->encoder_id; |
| found = SDL_TRUE; |
| break; |
| } |
| } |
| } |
| |
| if (found == SDL_TRUE) { |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Found encoder %d.", data->encoder_id); |
| break; |
| } |
| |
| KMSDRM_drmModeFreeEncoder(encoder); |
| encoder = NULL; |
| } |
| |
| if (i == resources->count_encoders) { |
| ret = SDL_SetError("No connected encoder found."); |
| goto cleanup; |
| } |
| |
| vdata->saved_crtc = KMSDRM_drmModeGetCrtc(vdata->drm_fd, encoder->crtc_id); |
| |
| if (vdata->saved_crtc == NULL) { |
| for (i = 0; i < resources->count_crtcs; i++) { |
| if (encoder->possible_crtcs & (1 << i)) { |
| encoder->crtc_id = resources->crtcs[i]; |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Set encoder's CRTC to %d.", encoder->crtc_id); |
| vdata->saved_crtc = KMSDRM_drmModeGetCrtc(vdata->drm_fd, encoder->crtc_id); |
| break; |
| } |
| } |
| } |
| |
| if (vdata->saved_crtc == NULL) { |
| ret = SDL_SetError("No CRTC found."); |
| goto cleanup; |
| } |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Saved crtc_id %u, fb_id %u, (%u,%u), %ux%u", |
| vdata->saved_crtc->crtc_id, vdata->saved_crtc->buffer_id, vdata->saved_crtc->x, |
| vdata->saved_crtc->y, vdata->saved_crtc->width, vdata->saved_crtc->height); |
| data->crtc_id = encoder->crtc_id; |
| data->cur_mode = vdata->saved_crtc->mode; |
| vdata->crtc_id = encoder->crtc_id; |
| |
| // select default mode if this one is not valid |
| if (vdata->saved_crtc->mode_valid == 0) { |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, |
| "Current mode is invalid, selecting connector's mode #0."); |
| data->cur_mode = connector->modes[0]; |
| } |
| |
| SDL_zero(current_mode); |
| |
| current_mode.w = data->cur_mode.hdisplay; |
| current_mode.h = data->cur_mode.vdisplay; |
| current_mode.refresh_rate = data->cur_mode.vrefresh; |
| |
| /* FIXME ? |
| drmModeFB *fb = drmModeGetFB(vdata->drm_fd, vdata->saved_crtc->buffer_id); |
| current_mode.format = drmToSDLPixelFormat(fb->bpp, fb->depth); |
| drmModeFreeFB(fb); |
| */ |
| current_mode.format = SDL_PIXELFORMAT_ARGB8888; |
| |
| current_mode.driverdata = NULL; |
| |
| SDL_zero(display); |
| display.desktop_mode = current_mode; |
| display.current_mode = current_mode; |
| |
| display.driverdata = data; |
| /* SDL_VideoQuit will later SDL_free(display.driverdata) */ |
| SDL_AddVideoDisplay(&display); |
| |
| /* Setup page flip handler */ |
| vdata->drm_pollfd.fd = vdata->drm_fd; |
| vdata->drm_pollfd.events = POLLIN; |
| vdata->drm_evctx.version = DRM_EVENT_CONTEXT_VERSION; |
| vdata->drm_evctx.page_flip_handler = KMSDRM_FlipHandler; |
| |
| #ifdef SDL_INPUT_LINUXEV |
| SDL_EVDEV_Init(); |
| #endif |
| |
| KMSDRM_InitMouse(_this); |
| |
| return ret; |
| |
| cleanup: |
| if (encoder != NULL) |
| KMSDRM_drmModeFreeEncoder(encoder); |
| if (connector != NULL) |
| KMSDRM_drmModeFreeConnector(connector); |
| if (resources != NULL) |
| KMSDRM_drmModeFreeResources(resources); |
| |
| if (ret != 0) { |
| /* Error (complete) cleanup */ |
| SDL_free(data); |
| if(vdata->saved_crtc != NULL) { |
| KMSDRM_drmModeFreeCrtc(vdata->saved_crtc); |
| vdata->saved_crtc = NULL; |
| } |
| if (vdata->gbm != NULL) { |
| KMSDRM_gbm_device_destroy(vdata->gbm); |
| vdata->gbm = NULL; |
| } |
| if (vdata->drm_fd >= 0) { |
| close(vdata->drm_fd); |
| vdata->drm_fd = -1; |
| } |
| } |
| return ret; |
| } |
| |
| void |
| KMSDRM_VideoQuit(_THIS) |
| { |
| SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); |
| |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoQuit()"); |
| |
| if (_this->gl_config.driver_loaded) { |
| SDL_GL_UnloadLibrary(); |
| } |
| |
| if(vdata->saved_crtc != NULL) { |
| if(vdata->drm_fd >= 0 && vdata->saved_conn_id > 0) { |
| /* Restore saved CRTC settings */ |
| drmModeCrtc *crtc = vdata->saved_crtc; |
| if(KMSDRM_drmModeSetCrtc(vdata->drm_fd, crtc->crtc_id, crtc->buffer_id, |
| crtc->x, crtc->y, &vdata->saved_conn_id, 1, |
| &crtc->mode) != 0) { |
| SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not restore original CRTC mode"); |
| } |
| } |
| KMSDRM_drmModeFreeCrtc(vdata->saved_crtc); |
| vdata->saved_crtc = NULL; |
| } |
| if (vdata->gbm != NULL) { |
| KMSDRM_gbm_device_destroy(vdata->gbm); |
| vdata->gbm = NULL; |
| } |
| if (vdata->drm_fd >= 0) { |
| close(vdata->drm_fd); |
| SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Closed DRM FD %d", vdata->drm_fd); |
| vdata->drm_fd = -1; |
| } |
| #ifdef SDL_INPUT_LINUXEV |
| SDL_EVDEV_Quit(); |
| #endif |
| } |
| |
| void |
| KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay * display) |
| { |
| /* Only one display mode available, the current one */ |
| SDL_AddDisplayMode(display, &display->current_mode); |
| } |
| |
| int |
| KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) |
| { |
| return 0; |
| } |
| |
| int |
| KMSDRM_CreateWindow(_THIS, SDL_Window * window) |
| { |
| SDL_WindowData *wdata; |
| SDL_VideoDisplay *display; |
| SDL_VideoData *vdata = ((SDL_VideoData *)_this->driverdata); |
| Uint32 surface_fmt, surface_flags; |
| |
| /* Allocate window internal data */ |
| wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData)); |
| if (wdata == NULL) { |
| SDL_OutOfMemory(); |
| goto error; |
| } |
| |
| wdata->waiting_for_flip = SDL_FALSE; |
| display = SDL_GetDisplayForWindow(window); |
| |
| /* Windows have one size for now */ |
| window->w = display->desktop_mode.w; |
| window->h = display->desktop_mode.h; |
| |
| /* Maybe you didn't ask for a fullscreen OpenGL window, but that's what you get */ |
| window->flags |= (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL); |
| |
| surface_fmt = GBM_FORMAT_XRGB8888; |
| surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; |
| |
| if (!KMSDRM_gbm_device_is_format_supported(vdata->gbm, surface_fmt, surface_flags)) { |
| SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "GBM surface format not supported. Trying anyway."); |
| } |
| wdata->gs = KMSDRM_gbm_surface_create(vdata->gbm, window->w, window->h, surface_fmt, surface_flags); |
| |
| #if SDL_VIDEO_OPENGL_EGL |
| if (!_this->egl_data) { |
| if (SDL_GL_LoadLibrary(NULL) < 0) { |
| goto error; |
| } |
| } |
| SDL_EGL_SetRequiredVisualId(_this, surface_fmt); |
| wdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wdata->gs); |
| |
| if (wdata->egl_surface == EGL_NO_SURFACE) { |
| SDL_SetError("Could not create EGL window surface"); |
| goto error; |
| } |
| #endif /* SDL_VIDEO_OPENGL_EGL */ |
| |
| /* In case we want low-latency, double-buffer video, we take note here */ |
| wdata->double_buffer = SDL_FALSE; |
| if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) { |
| wdata->double_buffer = SDL_TRUE; |
| } |
| |
| /* Window is created, but we have yet to set up CRTC to one of the GBM buffers if we want |
| drmModePageFlip to work, and we can't do it until EGL is completely setup, because we |
| need to do eglSwapBuffers so we can get a valid GBM buffer object to call |
| drmModeSetCrtc on it. */ |
| wdata->crtc_ready = SDL_FALSE; |
| |
| /* Setup driver data for this window */ |
| window->driverdata = wdata; |
| |
| /* One window, it always has focus */ |
| SDL_SetMouseFocus(window); |
| SDL_SetKeyboardFocus(window); |
| |
| /* Window has been successfully created */ |
| return 0; |
| |
| error: |
| if (wdata != NULL) { |
| #if SDL_VIDEO_OPENGL_EGL |
| if (wdata->egl_surface != EGL_NO_SURFACE) |
| SDL_EGL_DestroySurface(_this, wdata->egl_surface); |
| #endif /* SDL_VIDEO_OPENGL_EGL */ |
| if (wdata->gs != NULL) |
| KMSDRM_gbm_surface_destroy(wdata->gs); |
| SDL_free(wdata); |
| } |
| return -1; |
| } |
| |
| void |
| KMSDRM_DestroyWindow(_THIS, SDL_Window * window) |
| { |
| SDL_WindowData *data = (SDL_WindowData *) window->driverdata; |
| if(data) { |
| /* Wait for any pending page flips and unlock buffer */ |
| KMSDRM_WaitPageFlip(_this, data, -1); |
| if (data->crtc_bo != NULL) { |
| KMSDRM_gbm_surface_release_buffer(data->gs, data->crtc_bo); |
| data->crtc_bo = NULL; |
| } |
| if (data->next_bo != NULL) { |
| KMSDRM_gbm_surface_release_buffer(data->gs, data->next_bo); |
| data->next_bo = NULL; |
| } |
| if (data->current_bo != NULL) { |
| KMSDRM_gbm_surface_release_buffer(data->gs, data->current_bo); |
| data->current_bo = NULL; |
| } |
| #if SDL_VIDEO_OPENGL_EGL |
| SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
| if (data->egl_surface != EGL_NO_SURFACE) { |
| SDL_EGL_DestroySurface(_this, data->egl_surface); |
| } |
| #endif /* SDL_VIDEO_OPENGL_EGL */ |
| if (data->gs != NULL) { |
| KMSDRM_gbm_surface_destroy(data->gs); |
| data->gs = NULL; |
| } |
| SDL_free(data); |
| window->driverdata = NULL; |
| } |
| } |
| |
| int |
| KMSDRM_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) |
| { |
| return -1; |
| } |
| |
| void |
| KMSDRM_SetWindowTitle(_THIS, SDL_Window * window) |
| { |
| } |
| void |
| KMSDRM_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon) |
| { |
| } |
| void |
| KMSDRM_SetWindowPosition(_THIS, SDL_Window * window) |
| { |
| } |
| void |
| KMSDRM_SetWindowSize(_THIS, SDL_Window * window) |
| { |
| } |
| void |
| KMSDRM_ShowWindow(_THIS, SDL_Window * window) |
| { |
| } |
| void |
| KMSDRM_HideWindow(_THIS, SDL_Window * window) |
| { |
| } |
| void |
| KMSDRM_RaiseWindow(_THIS, SDL_Window * window) |
| { |
| } |
| void |
| KMSDRM_MaximizeWindow(_THIS, SDL_Window * window) |
| { |
| } |
| void |
| KMSDRM_MinimizeWindow(_THIS, SDL_Window * window) |
| { |
| } |
| void |
| KMSDRM_RestoreWindow(_THIS, SDL_Window * window) |
| { |
| } |
| void |
| KMSDRM_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed) |
| { |
| |
| } |
| |
| /*****************************************************************************/ |
| /* SDL Window Manager function */ |
| /*****************************************************************************/ |
| SDL_bool |
| KMSDRM_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info) |
| { |
| if (info->version.major <= SDL_MAJOR_VERSION) { |
| return SDL_TRUE; |
| } else { |
| SDL_SetError("application not compiled with SDL %d.%d\n", |
| SDL_MAJOR_VERSION, SDL_MINOR_VERSION); |
| return SDL_FALSE; |
| } |
| |
| /* Failed to get window manager information */ |
| return SDL_FALSE; |
| } |
| |
| #endif /* SDL_VIDEO_DRIVER_KMSDRM */ |
| |
| /* vi: set ts=4 sw=4 expandtab: */ |